@ -1,3 +1,5 @@
/// This package is in charge of connecting to the DB and migrations
package db
package db
import (
import (
@ -10,61 +12,95 @@ import (
var __version = 1
var __version = 1
type Log Ctx struct {
type Db Ctx struct {
db * sql . DB
db * sql . DB
version int
version int
}
}
func Init ( db_location string ) ( * LogCtx , error ) {
func initVersion ( tx * sql . Tx ) ( int , error ) {
db , err := sql . Open ( "sqlite3" , db_location )
var version int
if err != nil {
// Check the version
return nil , fmt . Errorf ( "Could not connect to DB. %w" , err )
if err := tx . QueryRow ( "PRAGMA user_version" ) . Scan ( & version ) ; err != nil {
}
tx . Rollback ( )
if err := db . Ping ( ) ; err != nil {
return 0 , fmt . Errorf ( "Could not select user_version. %w" , err )
return nil , fmt . Errorf ( "Could not ping DB. %w" , err )
}
}
ctx := context . Background ( )
if version == 0 {
tx , err := db . BeginTx ( ctx , nil )
_ , err := tx . Exec ( fmt . Sprintf ( "PRAGMA user_version=%d" , __version ) )
if err != nil {
if err != nil {
return nil , err
tx . Rollback ( )
return 0 , fmt . Errorf ( "Could not update pragma version. %w" , err )
}
version = __version
} else if version != __version {
tx . Rollback ( )
return 0 , errors . New ( fmt . Sprintf ( "Wrong version. Expected %d got %d" , __version , version ) )
}
return version , nil
}
}
func migration0 ( tx * sql . Tx ) error {
// Optionally add the version table
// Optionally add the version table
if _ , err := tx . Exec ( `
if _ , err := tx . Exec ( `
create table if not exists eng_log_version ( id integer not null ) ;
create table if not exists eng_log_version ( id integer not null ) ;
` ) ; err != nil {
` ) ; err != nil {
tx . Rollback ( )
tx . Rollback ( )
return nil , fmt . Errorf ( "Could not create eng_log_version. %w" , err )
return fmt . Errorf ( "Could not create eng_log_version. %w" , err )
}
}
// Optionally add the log table
// Optionally add the log table
if _ , err := tx . Exec ( `
if _ , err := tx . Exec ( `
create table if not exists log ( id integer not null primary key , title string )
create table if not exists log ( id integer not null primary key , title string )
` ) ; err != nil {
` ) ; err != nil {
tx . Rollback ( )
tx . Rollback ( )
return nil , fmt . Errorf ( "Could not create log. %w" , err )
return fmt . Errorf ( "Could not create log. %w" , err )
}
return nil
}
}
var version int
func initMigrations ( tx * sql . Tx , start_from_versiono int ) error {
// Check the version
var migrations = [ ] func ( * sql . Tx ) error { migration0 }
if err := tx . QueryRow ( "SELECT IFNULL((SELECT id FROM eng_log_version LIMIT 1), 0)" ) . Scan ( & version ) ; err != nil {
for migration_idx , migration := range migrations {
// Version is 1 indexed, while the migration_idx is 0 indexed
var migration_num = migration_idx + 1
if migration_num < start_from_versiono {
continue
}
err := migration ( tx )
if err != nil {
tx . Rollback ( )
tx . Rollback ( )
return nil , fmt . Errorf ( "Could not query for eng_log_version id. %w" , err )
return fmt . Errorf ( "Failed migration %d. %w" , migration_num , err )
}
}
return nil
}
}
if version == 0 {
func Init ( db_location string ) ( * DbCtx , error ) {
_ , err := tx . Exec ( "INSERT INTO eng_log_version (id) VALUES (?)" , __version )
db , err := sql . Open ( "sqlite3" , db_locat ion)
if err != nil {
if err != nil {
tx . Rollback ( )
return nil , fmt . Errorf ( "Could not connect to DB. %w" , err )
return nil , fmt . Errorf ( "Could not insert log-version. %w" , err )
}
}
version = __version
if err := db . Ping ( ) ; err != nil {
} else if version != __version {
return nil , fmt . Errorf ( "Could not ping DB. %w" , err )
tx . Rollback ( )
}
return nil , errors . New ( fmt . Sprintf ( "Wrong version. Expected %d got %d" , __version , version ) )
ctx := context . Background ( )
tx , err := db . BeginTx ( ctx , nil )
if err != nil {
return nil , err
}
version , err := initVersion ( tx )
if err != nil {
return nil , err
}
err = initMigrations ( tx , version )
if err != nil {
return nil , err
}
}
tx . Commit ( )
tx . Commit ( )
return & LogCtx { db , version } , nil
return & Db Ctx{ db , version } , nil
}
}