Commit 68a77c40 by Torkel Ödegaard

More progress on db schema setup and migrations, tricky stuff

parent 38f237ef
db:
mysql:
image: mysql:latest
environment:
MYSQL_ROOT_PASSWORD: rootpass
MYSQL_DATABASE: grafana
MYSQL_USER: grafana
MYSQL_PASSWORD: password
ports:
- "3306:3306"
mysqltests:
image: mysql:latest
environment:
MYSQL_ROOT_PASSWORD: rootpass
MYSQL_DATABASE: grafana_tests
MYSQL_USER: grafana
MYSQL_PASSWORD: password
ports:
- "3306:3306"
openldap:
image: cnry/openldap
mysqltests:
image: mysql:latest
environment:
SLAPD_PASSWORD: grafana
SLAPD_DOMAIN: grafana.org
MYSQL_ROOT_PASSWORD: rootpass
MYSQL_DATABASE: grafana_tests
MYSQL_USER: grafana
MYSQL_PASSWORD: password
ports:
- "389:389"
- "3306:3306"
......@@ -8,9 +8,8 @@ import (
func GetAccount(c *middleware.Context) {
query := m.GetAccountInfoQuery{Id: c.AccountId}
err := bus.Dispatch(&query)
if err != nil {
if err := bus.Dispatch(&query); err != nil {
c.JsonApiErr(500, "Failed to fetch collaboratos", err)
return
}
......@@ -31,9 +30,8 @@ func UpdateAccount(c *middleware.Context, cmd m.UpdateAccountCommand) {
func GetOtherAccounts(c *middleware.Context) {
query := m.GetOtherAccountsQuery{AccountId: c.AccountId}
err := bus.Dispatch(&query)
if err != nil {
if err := bus.Dispatch(&query); err != nil {
c.JsonApiErr(500, "Failed to get other accounts", err)
return
}
......
......@@ -3,9 +3,27 @@ package migrations
type migration struct {
desc string
sqlite string
mysql string
verifyTable string
}
type columnType string
const (
DB_TYPE_STRING columnType = "String"
)
func (m *migration) getSql(dbType string) string {
switch dbType {
case "mysql":
return m.mysql
case "sqlite3":
return m.sqlite
}
panic("db type not supported")
}
type migrationBuilder struct {
migration *migration
}
......@@ -15,6 +33,11 @@ func (b *migrationBuilder) sqlite(sql string) *migrationBuilder {
return b
}
func (b *migrationBuilder) mysql(sql string) *migrationBuilder {
b.migration.mysql = sql
return b
}
func (b *migrationBuilder) verifyTable(name string) *migrationBuilder {
b.migration.verifyTable = name
return b
......
......@@ -4,8 +4,12 @@ import (
"errors"
"fmt"
"github.com/go-xorm/xorm"
"github.com/torkelo/grafana-pro/pkg/services/sqlstore/sqlsyntax"
_ "github.com/go-sql-driver/mysql"
"github.com/go-xorm/xorm"
_ "github.com/lib/pq"
_ "github.com/mattn/go-sqlite3"
)
var x *xorm.Engine
......@@ -29,9 +33,18 @@ func getSchemaVersion() (int, error) {
return v.Version, err
}
func StartMigration(engine *xorm.Engine) error {
func setEngineAndDialect(engine *xorm.Engine) {
x = engine
dialect = new(sqlsyntax.Sqlite3)
switch x.DriverName() {
case "mysql":
dialect = new(sqlsyntax.Mysql)
case "sqlite3":
dialect = new(sqlsyntax.Sqlite3)
}
}
func StartMigration(engine *xorm.Engine) error {
setEngineAndDialect(engine)
_, err := getSchemaVersion()
if err != nil {
......@@ -49,16 +62,21 @@ func StartMigration(engine *xorm.Engine) error {
func execMigration(m *migration) error {
err := inTransaction(func(sess *xorm.Session) error {
_, err := sess.Exec(m.sqlite)
_, err := sess.Exec(m.getSql(x.DriverName()))
if err != nil {
return err
}
return nil
})
if err != nil {
return err
}
// verify
return verifyMigration(m)
}
func verifyMigration(m *migration) error {
if m.verifyTable != "" {
sqlStr, args := dialect.TableCheckSql(m.verifyTable)
results, err := x.Query(sqlStr, args...)
......@@ -66,7 +84,6 @@ func execMigration(m *migration) error {
return errors.New(fmt.Sprintf("Verify failed: table %v does not exist", m.verifyTable))
}
}
return nil
}
......
......@@ -4,13 +4,24 @@ var migrationList []*migration
func init() {
new(migrationBuilder).
// ------------------------------
desc("Create account table").
sqlite(`
CREATE TABLE account (
id INTEGER PRIMARY KEY
id INTEGER PRIMARY KEY AUTOINCREMENT
)
`).
verifyTable("account")
mysql(`
CREATE TABLE account (
id BIGINT NOT NULL AUTO_INCREMENT, PRIMARY KEY (id)
)
`).
verifyTable("account").add()
// ------------------------------
// desc("Add name column to account table").
// table("account").addColumn("name").colType(DB_TYPE_STRING)
// sqlite("ALTER TABLE account ADD COLUMN name TEXT").
// mysql("ALTER TABLE account ADD COLUMN name NVARCHAR(255)").
}
type SchemaVersion struct {
......
package migrations
// import (
// "testing"
//
// "github.com/go-xorm/xorm"
//
// . "github.com/smartystreets/goconvey/convey"
// )
//
// func TestMigrationsSqlite(t *testing.T) {
//
// Convey("Initial SQLite3 migration", t, func() {
// x, err := xorm.NewEngine("sqlite3", ":memory:")
// StartMigration(x)
//
// tables, err := x.DBMetas()
// So(err, ShouldBeNil)
//
// So(len(tables), ShouldEqual, 1)
// })
// }
import (
"fmt"
"testing"
"github.com/go-xorm/xorm"
. "github.com/smartystreets/goconvey/convey"
)
func cleanDB(x *xorm.Engine) {
tables, _ := x.DBMetas()
sess := x.NewSession()
defer sess.Close()
for _, table := range tables {
if _, err := sess.Exec("SET FOREIGN_KEY_CHECKS = 0"); err != nil {
panic("Failed to disable foreign key checks")
}
if _, err := sess.Exec("DROP TABLE " + table.Name); err != nil {
panic(fmt.Sprintf("Failed to delete table: %v, err: %v", table.Name, err))
}
if _, err := sess.Exec("SET FOREIGN_KEY_CHECKS = 1"); err != nil {
panic("Failed to disable foreign key checks")
}
}
}
func TestMigrationsSqlite(t *testing.T) {
testDBs := [][]string{
[]string{"sqlite3", ":memory:"},
[]string{"mysql", "grafana:password@tcp(localhost:3306)/grafana_tests?charset=utf8"},
}
for _, testDB := range testDBs {
Convey("Initial "+testDB[0]+" migration", t, func() {
x, err := xorm.NewEngine(testDB[0], testDB[1])
So(err, ShouldBeNil)
if testDB[0] == "mysql" {
cleanDB(x)
}
StartMigration(x)
tables, err := x.DBMetas()
So(err, ShouldBeNil)
So(len(tables), ShouldEqual, 2)
})
}
}
......@@ -8,11 +8,24 @@ type Dialect interface {
type Sqlite3 struct {
}
type Mysql struct {
}
func (db *Sqlite3) DBType() string {
return "sqlite3"
}
func (db *Mysql) DBType() string {
return "mysql"
}
func (db *Sqlite3) TableCheckSql(tableName string) (string, []interface{}) {
args := []interface{}{tableName}
return "SELECT name FROM sqlite_master WHERE type='table' and name = ?", args
}
func (db *Mysql) TableCheckSql(tableName string) (string, []interface{}) {
args := []interface{}{"grafana", tableName}
sql := "SELECT `TABLE_NAME` from `INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_SCHEMA`=? and `TABLE_NAME`=?"
return sql, args
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment