diff --git a/pkg/db/db.go b/pkg/db/db.go new file mode 100644 index 000000000..73b0c135e --- /dev/null +++ b/pkg/db/db.go @@ -0,0 +1,81 @@ +// Vikunja is a todo-list application to facilitate your life. +// Copyright 2019 Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package db + +import ( + "code.vikunja.io/api/pkg/log" + "encoding/gob" + "fmt" + "github.com/go-xorm/core" + "github.com/go-xorm/xorm" + xrc "github.com/go-xorm/xorm-redis-cache" + "github.com/spf13/viper" + + _ "github.com/go-sql-driver/mysql" // Because. + _ "github.com/mattn/go-sqlite3" // Because. +) + +// CreateDBEngine initializes a db engine from the config +func CreateDBEngine() (engine *xorm.Engine, err error) { + // Use Mysql if set + if viper.GetString("database.type") == "mysql" { + connStr := fmt.Sprintf( + "%s:%s@tcp(%s)/%s?charset=utf8&parseTime=true", + viper.GetString("database.user"), + viper.GetString("database.password"), + viper.GetString("database.host"), + viper.GetString("database.database")) + e, err := xorm.NewEngine("mysql", connStr) + e.SetMaxOpenConns(viper.GetInt("database.openconnections")) + return e, err + } + + // Otherwise use sqlite + path := viper.GetString("database.path") + if path == "" { + path = "./db.db" + } + + engine, err = xorm.NewEngine("sqlite3", path) + if err != nil { + return nil, err + } + + // Cache + if viper.GetBool("cache.enabled") { + switch viper.GetString("cache.type") { + case "memory": + cacher := xorm.NewLRUCacher(xorm.NewMemoryStore(), viper.GetInt("cache.maxelementsize")) + engine.SetDefaultCacher(cacher) + case "redis": + cacher := xrc.NewRedisCacher(viper.GetString("redis.host"), viper.GetString("redis.password"), xrc.DEFAULT_EXPIRATION, x.Logger()) + engine.SetDefaultCacher(cacher) + // Get the tables from migration + gob.Register(tables) + gob.Register(tablesWithPointer) // Need to register tables with pointer as well... + default: + log.Log.Info("Did not find a valid cache type. Caching disabled. Please refer to the docs for poosible cache types.") + } + } + + engine.SetMapper(core.GonicMapper{}) + + engine.ShowSQL(viper.GetString("log.database") != "off") + engine.SetLogger(xorm.NewSimpleLogger(log.GetLogWriter("database"))) + + return +} diff --git a/pkg/migration/migration.go b/pkg/migration/migration.go index bcf325d55..1920b0058 100644 --- a/pkg/migration/migration.go +++ b/pkg/migration/migration.go @@ -17,6 +17,9 @@ package migration import ( + "code.vikunja.io/api/pkg/db" + "code.vikunja.io/api/pkg/log" + "github.com/go-xorm/xorm" "sort" "src.techknowlogick.com/xormigrate" ) @@ -25,13 +28,31 @@ import ( var migrations []*xormigrate.Migration -func Migrate() { +func Migrate(x *xorm.Engine) { + // Get our own xorm engine if we don't have one + if x == nil { + var err error + x, err = db.CreateDBEngine() + if err != nil { + log.Log.Criticalf("Could not connect to db: %v", err.Error()) + return + } + } + // Because init() does not guarantee the order in which these are added to the slice, // we need to sort them to ensure that they are in order sort.Slice(migrations, func(i, j int) bool { return migrations[i].ID < migrations[j].ID }) + m := xormigrate.New(nil, migrations) + + m.NewLogger(log.GetLogWriter("database")) + + m.InitSchema() + + // TODO: Init schema + /* XORM logs from try.vikunja.io: diff --git a/pkg/models/models.go b/pkg/models/models.go index 03c47afe9..b96b69b1f 100644 --- a/pkg/models/models.go +++ b/pkg/models/models.go @@ -17,13 +17,11 @@ package models import ( + "code.vikunja.io/api/pkg/db" "code.vikunja.io/api/pkg/log" - "encoding/gob" - "fmt" + "code.vikunja.io/api/pkg/migration" _ "github.com/go-sql-driver/mysql" // Because. - "github.com/go-xorm/core" "github.com/go-xorm/xorm" - xrc "github.com/go-xorm/xorm-redis-cache" _ "github.com/mattn/go-sqlite3" // Because. "github.com/spf13/viper" ) @@ -35,28 +33,6 @@ var ( tablesWithPointer []interface{} ) -func getEngine() (*xorm.Engine, error) { - // Use Mysql if set - if viper.GetString("database.type") == "mysql" { - connStr := fmt.Sprintf( - "%s:%s@tcp(%s)/%s?charset=utf8&parseTime=true", - viper.GetString("database.user"), - viper.GetString("database.password"), - viper.GetString("database.host"), - viper.GetString("database.database")) - e, err := xorm.NewEngine("mysql", connStr) - e.SetMaxOpenConns(viper.GetInt("database.openconnections")) - return e, err - } - - // Otherwise use sqlite - path := viper.GetString("database.path") - if path == "" { - path = "./db.db" - } - return xorm.NewEngine("sqlite3", path) -} - func init() { tables = append(tables, new(User), @@ -93,36 +69,13 @@ func init() { // SetEngine sets the xorm.Engine func SetEngine() (err error) { - x, err = getEngine() + x, err = db.CreateDBEngine() if err != nil { - return fmt.Errorf("failed to connect to database: %v", err) + log.Log.Criticalf("Could not connect to db: %v", err.Error()) + return } - // Cache - if viper.GetBool("cache.enabled") { - switch viper.GetString("cache.type") { - case "memory": - cacher := xorm.NewLRUCacher(xorm.NewMemoryStore(), viper.GetInt("cache.maxelementsize")) - x.SetDefaultCacher(cacher) - case "redis": - cacher := xrc.NewRedisCacher(viper.GetString("redis.host"), viper.GetString("redis.password"), xrc.DEFAULT_EXPIRATION, x.Logger()) - x.SetDefaultCacher(cacher) - gob.Register(tables) - gob.Register(tablesWithPointer) // Need to register tables with pointer as well... - default: - log.Log.Info("Did not find a valid cache type. Caching disabled. Please refer to the docs for poosible cache types.") - } - } - - x.SetMapper(core.GonicMapper{}) - - // Sync dat shit - if err = x.StoreEngine("InnoDB").Sync2(tables...); err != nil { - return fmt.Errorf("sync database struct error: %v", err) - } - - x.ShowSQL(viper.GetString("log.database") != "off") - x.SetLogger(xorm.NewSimpleLogger(log.GetLogWriter("database"))) + migration.Migrate(x) return nil }