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/20190324205606.go b/pkg/migration/20190324205606.go index a138d474c..18956f890 100644 --- a/pkg/migration/20190324205606.go +++ b/pkg/migration/20190324205606.go @@ -15,3 +15,23 @@ // along with this program. If not, see . package migration + +import ( + "github.com/go-xorm/xorm" + "src.techknowlogick.com/xormigrate" +) + +func init() { + migrations = append(migrations, &xormigrate.Migration{ + ID: "20190324205606", + Description: "Lorem Ipsum", + Migrate: func(tx *xorm.Engine) error { + + return nil + }, + Rollback: func(tx *xorm.Engine) error { + + return nil + }, + }) +} diff --git a/pkg/migration/migration.go b/pkg/migration/migration.go index 2e4d0f631..1920b0058 100644 --- a/pkg/migration/migration.go +++ b/pkg/migration/migration.go @@ -16,73 +16,101 @@ package migration -import "src.techknowlogick.com/xormigrate" +import ( + "code.vikunja.io/api/pkg/db" + "code.vikunja.io/api/pkg/log" + "github.com/go-xorm/xorm" + "sort" + "src.techknowlogick.com/xormigrate" +) // You can get the id string for new migrations by running `date +%Y%m%d%H%M%S` on a unix system. 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: + XORM logs from try.vikunja.io: - Table users Column email db default is 'NULL', struct default is - Table users Column is_active db default is NULL, struct default is - Table users Column password_reset_token db default is 'NULL', struct default is - Table users Column email_confirm_token db default is 'NULL', struct default is - Table users Column created db default is NULL, struct default is - Table users Column updated db default is NULL, struct default is - Table list Column title db default is 'NULL', struct default is - Table list Column description db default is 'NULL', struct default is - Table list Column owner_id db default is NULL, struct default is - Table list Column namespace_id db default is NULL, struct default is - Table list Column created db default is NULL, struct default is - Table list Column updated db default is NULL, struct default is - Table tasks Column text db default is 'NULL', struct default is - Table tasks Column description db default is 'NULL', struct default is - Table tasks Column done db default is NULL, struct default is - Table tasks Column due_date_unix db default is NULL, struct default is - Table tasks Column reminders_unix db default is 'NULL', struct default is - Table tasks Column created_by_id db default is NULL, struct default is - Table tasks Column list_id db default is NULL, struct default is - Table tasks Column repeat_after db default is NULL, struct default is - Table tasks Column parent_task_id db default is NULL, struct default is - Table tasks Column priority db default is NULL, struct default is - Table tasks Column start_date_unix db default is NULL, struct default is - Table tasks Column end_date_unix db default is NULL, struct default is - Table tasks Column created db default is NULL, struct default is - Table tasks Column updated db default is NULL, struct default is - Table teams Column description db default is 'NULL', struct default is - Table teams Column created db default is NULL, struct default is - Table teams Column updated db default is NULL, struct default is - Table team_members Column admin db default is NULL, struct default is - Table team_members Column created db default is NULL, struct default is - Table team_list Column right db default is NULL, struct default is - Table team_list Column created db default is NULL, struct default is - Table team_list Column updated db default is NULL, struct default is - Table team_namespaces Column right db default is NULL, struct default is - Table team_namespaces Column created db default is NULL, struct default is - Table team_namespaces Column updated db default is NULL, struct default is - Table namespaces Column name db default is 'NULL', struct default is - Table namespaces Column description db default is 'NULL', struct default is - Table namespaces Column created db default is NULL, struct default is - Table namespaces Column updated db default is NULL, struct default is - Table users_list Column right db default is NULL, struct default is - Table users_list Column created db default is NULL, struct default is - Table users_list Column updated db default is NULL, struct default is - Table users_namespace Column right db default is NULL, struct default is - Table users_namespace Column created db default is NULL, struct default is - Table users_namespace Column updated db default is NULL, struct default is - Table task_assignees Column created db default is NULL, struct default is - Table labels Column description db default is 'NULL', struct default is - Table labels Column hex_color db default is 'NULL', struct default is - Table labels Column created db default is NULL, struct default is - Table labels Column updated db default is NULL, struct default is - Table label_task Column created db default is NULL, struct default is - Table tasks has column reminder_unix but struct has not related field - Table team_members has column updated but struct has not related field + Table users Column email db default is 'NULL', struct default is + Table users Column is_active db default is NULL, struct default is + Table users Column password_reset_token db default is 'NULL', struct default is + Table users Column email_confirm_token db default is 'NULL', struct default is + Table users Column created db default is NULL, struct default is + Table users Column updated db default is NULL, struct default is + Table list Column title db default is 'NULL', struct default is + Table list Column description db default is 'NULL', struct default is + Table list Column owner_id db default is NULL, struct default is + Table list Column namespace_id db default is NULL, struct default is + Table list Column created db default is NULL, struct default is + Table list Column updated db default is NULL, struct default is + Table tasks Column text db default is 'NULL', struct default is + Table tasks Column description db default is 'NULL', struct default is + Table tasks Column done db default is NULL, struct default is + Table tasks Column due_date_unix db default is NULL, struct default is + Table tasks Column reminders_unix db default is 'NULL', struct default is + Table tasks Column created_by_id db default is NULL, struct default is + Table tasks Column list_id db default is NULL, struct default is + Table tasks Column repeat_after db default is NULL, struct default is + Table tasks Column parent_task_id db default is NULL, struct default is + Table tasks Column priority db default is NULL, struct default is + Table tasks Column start_date_unix db default is NULL, struct default is + Table tasks Column end_date_unix db default is NULL, struct default is + Table tasks Column created db default is NULL, struct default is + Table tasks Column updated db default is NULL, struct default is + Table teams Column description db default is 'NULL', struct default is + Table teams Column created db default is NULL, struct default is + Table teams Column updated db default is NULL, struct default is + Table team_members Column admin db default is NULL, struct default is + Table team_members Column created db default is NULL, struct default is + Table team_list Column right db default is NULL, struct default is + Table team_list Column created db default is NULL, struct default is + Table team_list Column updated db default is NULL, struct default is + Table team_namespaces Column right db default is NULL, struct default is + Table team_namespaces Column created db default is NULL, struct default is + Table team_namespaces Column updated db default is NULL, struct default is + Table namespaces Column name db default is 'NULL', struct default is + Table namespaces Column description db default is 'NULL', struct default is + Table namespaces Column created db default is NULL, struct default is + Table namespaces Column updated db default is NULL, struct default is + Table users_list Column right db default is NULL, struct default is + Table users_list Column created db default is NULL, struct default is + Table users_list Column updated db default is NULL, struct default is + Table users_namespace Column right db default is NULL, struct default is + Table users_namespace Column created db default is NULL, struct default is + Table users_namespace Column updated db default is NULL, struct default is + Table task_assignees Column created db default is NULL, struct default is + Table labels Column description db default is 'NULL', struct default isdfdfsd + Table labels Column hex_color db default is 'NULL', struct default is + Table labels Column created db default is NULL, struct default is + Table labels Column updated db default is NULL, struct default is + Table label_task Column created db default is NULL, struct default is + + Table tasks has column reminder_unix but struct has not related field + Table team_members has column updated but struct has not related field */ } 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 }