DB Migrations #67

Merged
konrad merged 44 commits from feature/migrations into master 2019-03-29 17:54:36 +00:00
4 changed files with 193 additions and 111 deletions
Showing only changes of commit ef6377f2ae - Show all commits

81
pkg/db/db.go Normal file
View File

@ -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 <https://www.gnu.org/licenses/>.
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
}

View File

@ -15,3 +15,23 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
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
},
})
}

View File

@ -16,15 +16,42 @@
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:
@ -77,11 +104,12 @@ func Migrate() {
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 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
*/

View File

@ -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
}