1
0
Fork 0
mirror of https://github.com/Eggbertx/gochan.git synced 2025-08-10 12:56:24 -07:00
gochan/pkg/gcsql/databasecheck.go

129 lines
3.9 KiB
Go

package gcsql
import (
"errors"
"github.com/gochan-org/gochan/pkg/config"
"github.com/gochan-org/gochan/pkg/gclog"
)
const (
DBIsPreApril = 1 << iota
DBCorrupted
DBClean
DBModernButBehind
DBUpToDate
DBModernButAhead
targetDatabaseVersion = 1
)
var (
// ErrInvalidVersion is used when the db contains a database_version table
// but zero or more than one versions were found
ErrInvalidVersion = errors.New("database contains database_version table but zero or more than one versions were found")
)
// GetCompleteDatabaseVersion checks the database for any versions and errors that may exist.
// If a version is found, execute the version check. Otherwise check for deprecated info
// If no deprecated info is found, check if any databases exist prefixed with config.DBprefix
// if no prefixed databases exist, assume this is a new installation
func GetCompleteDatabaseVersion() (dbVersion, dbFlag int, err error) {
versionTableExists, err := doesTableExist("database_version")
if err != nil {
return 0, 0, err
}
if versionTableExists {
databaseVersion, versionError := getDatabaseVersion(GochanVersionKeyConstant)
if versionError != nil {
return 0, 0, ErrInvalidVersion
}
if databaseVersion < targetDatabaseVersion {
return databaseVersion, DBModernButBehind, nil
}
if databaseVersion > targetDatabaseVersion {
return databaseVersion, DBModernButAhead, nil
}
return databaseVersion, DBUpToDate, nil
}
isOldDesign, err := doesTableExist("info")
if err != nil {
return 0, 0, err
}
if isOldDesign {
return 0, DBIsPreApril, nil
}
//No old or current database versioning tables found.
if config.GetSystemCriticalConfig().DBprefix != "" {
//Check if any gochan tables exist
gochanTableExists, err := doesGochanPrefixTableExist()
if err != nil {
return 0, 0, err
}
if gochanTableExists {
return 0, DBCorrupted, nil
}
}
return 0, DBClean, nil
}
//CheckAndInitializeDatabase checks the validity of the database and initialises it if it is empty
func CheckAndInitializeDatabase(dbType string) {
dbVersion, versionFlag, err := GetCompleteDatabaseVersion()
if err != nil {
gclog.Printf(FatalSQLFlags, "Failed to initialise database: %s", err.Error())
}
good := false
defer func() {
if !good {
return
}
if err = tmpSqlAdjust(); err != nil {
gclog.Print(FatalSQLFlags, "Failed updating database structure: ", err.Error())
return
}
}()
switch versionFlag {
case DBIsPreApril:
fallthrough
case DBModernButBehind:
gclog.Printf(FatalSQLFlags,
"Database layout is deprecated. Please run gochan-migrate. Target version is %d", targetDatabaseVersion) //TODO give exact command
case DBClean:
buildNewDatabase(dbType)
good = true
return
case DBUpToDate:
good = true
return
case DBCorrupted:
gclog.Println(FatalSQLFlags,
"Database contains gochan prefixed tables but is missing versioning tables. Database is possible corrupted. Please contact the devs for help.")
return
case DBModernButAhead:
gclog.Printf(gclog.LFatal,
"Database layout is ahead of current version. Current version %d, target version: %d.\n"+
"Are you running an old gochan version?", dbVersion, targetDatabaseVersion)
return
default:
gclog.Printf(FatalSQLFlags,
"Failed to initialise database: Checkdatabase, none of paths matched. Should never be executed. Check for outcome of GetCompleteDatabaseVersion()")
return
}
}
func buildNewDatabase(dbType string) {
var err error
if err = initDB("initdb_" + dbType + ".sql"); err != nil {
gclog.Print(FatalSQLFlags, "Failed initializing DB: ", err.Error())
}
err = CreateDefaultBoardIfNoneExist()
if err != nil {
gclog.Print(FatalSQLFlags, "Failed creating default board: ", err.Error())
}
err = CreateDefaultAdminIfNoStaff()
if err != nil {
gclog.Print(FatalSQLFlags, "Failed creating default admin account: ", err.Error())
}
gclog.Print(gclog.LStdLog|gclog.LErrorLog, "Finished building database...")
}