Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
a64a38d7
Commit
a64a38d7
authored
Jan 18, 2015
by
Torkel Ödegaard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added migration log and migration id, do not execute already executed migrations
parent
8bfed750
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
194 additions
and
65 deletions
+194
-65
pkg/services/sqlstore/migrations/builder.go
+18
-12
pkg/services/sqlstore/migrations/migrations.go
+15
-20
pkg/services/sqlstore/migrations/migrations_test.go
+8
-2
pkg/services/sqlstore/migrations/migrator.go
+75
-31
pkg/services/sqlstore/migrations/migrator_test.go
+78
-0
No files found.
pkg/services/sqlstore/migrations/builder.go
View file @
a64a38d7
...
@@ -13,6 +13,8 @@ const (
...
@@ -13,6 +13,8 @@ const (
type
Migration
interface
{
type
Migration
interface
{
Sql
(
dialect
Dialect
)
string
Sql
(
dialect
Dialect
)
string
Id
()
string
SetId
(
string
)
}
}
type
ColumnType
string
type
ColumnType
string
...
@@ -22,7 +24,15 @@ const (
...
@@ -22,7 +24,15 @@ const (
)
)
type
MigrationBase
struct
{
type
MigrationBase
struct
{
desc
string
id
string
}
func
(
m
*
MigrationBase
)
Id
()
string
{
return
m
.
id
}
func
(
m
*
MigrationBase
)
SetId
(
id
string
)
{
m
.
id
=
id
}
}
type
RawSqlMigration
struct
{
type
RawSqlMigration
struct
{
...
@@ -53,11 +63,6 @@ func (m *RawSqlMigration) Mysql(sql string) *RawSqlMigration {
...
@@ -53,11 +63,6 @@ func (m *RawSqlMigration) Mysql(sql string) *RawSqlMigration {
return
m
return
m
}
}
func
(
m
*
RawSqlMigration
)
Desc
(
desc
string
)
*
RawSqlMigration
{
m
.
desc
=
desc
return
m
}
type
AddColumnMigration
struct
{
type
AddColumnMigration
struct
{
MigrationBase
MigrationBase
tableName
string
tableName
string
...
@@ -90,16 +95,12 @@ func (m *AddColumnMigration) Sql(dialect Dialect) string {
...
@@ -90,16 +95,12 @@ func (m *AddColumnMigration) Sql(dialect Dialect) string {
return
fmt
.
Sprintf
(
"ALTER TABLE %s ADD COLUMN %s %s"
,
m
.
tableName
,
m
.
columnName
,
dialect
.
ToDBTypeSql
(
m
.
columnType
,
m
.
length
))
return
fmt
.
Sprintf
(
"ALTER TABLE %s ADD COLUMN %s %s"
,
m
.
tableName
,
m
.
columnName
,
dialect
.
ToDBTypeSql
(
m
.
columnType
,
m
.
length
))
}
}
func
(
m
*
AddColumnMigration
)
Desc
(
desc
string
)
*
AddColumnMigration
{
m
.
desc
=
desc
return
m
}
type
AddIndexMigration
struct
{
type
AddIndexMigration
struct
{
MigrationBase
MigrationBase
tableName
string
tableName
string
columns
string
columns
string
indexName
string
indexName
string
unique
string
}
}
func
(
m
*
AddIndexMigration
)
Name
(
name
string
)
*
AddIndexMigration
{
func
(
m
*
AddIndexMigration
)
Name
(
name
string
)
*
AddIndexMigration
{
...
@@ -112,11 +113,16 @@ func (m *AddIndexMigration) Table(tableName string) *AddIndexMigration {
...
@@ -112,11 +113,16 @@ func (m *AddIndexMigration) Table(tableName string) *AddIndexMigration {
return
m
return
m
}
}
func
(
m
*
AddIndexMigration
)
Unique
()
*
AddIndexMigration
{
m
.
unique
=
"UNIQUE"
return
m
}
func
(
m
*
AddIndexMigration
)
Columns
(
columns
...
string
)
*
AddIndexMigration
{
func
(
m
*
AddIndexMigration
)
Columns
(
columns
...
string
)
*
AddIndexMigration
{
m
.
columns
=
strings
.
Join
(
columns
,
","
)
m
.
columns
=
strings
.
Join
(
columns
,
","
)
return
m
return
m
}
}
func
(
m
*
AddIndexMigration
)
Sql
(
dialect
Dialect
)
string
{
func
(
m
*
AddIndexMigration
)
Sql
(
dialect
Dialect
)
string
{
return
fmt
.
Sprintf
(
"CREATE
UNIQUE INDEX %s ON %s(%s)"
,
m
.
indexName
,
m
.
tableName
,
m
.
columns
)
return
fmt
.
Sprintf
(
"CREATE
%s INDEX %s ON %s(%s)"
,
m
.
unique
,
m
.
indexName
,
m
.
tableName
,
m
.
columns
)
}
}
pkg/services/sqlstore/migrations/migrations.go
View file @
a64a38d7
package
migrations
package
migrations
var
migrationList
[]
Migration
import
"time"
// Id int64
// Id int64
// Login string `xorm:"UNIQUE NOT NULL"`
// Login string `xorm:"UNIQUE NOT NULL"`
...
@@ -16,9 +16,11 @@ var migrationList []Migration
...
@@ -16,9 +16,11 @@ var migrationList []Migration
// Created time.Time
// Created time.Time
// Updated time.Time
// Updated time.Time
func
init
()
{
func
AddMigrations
(
mg
*
Migrator
)
{
// ------------------------------
addMigration
(
new
(
RawSqlMigration
)
.
Desc
(
"Create account table"
)
.
// TABLE Account
// -------------------------------
mg
.
AddMigration
(
"create account table"
,
new
(
RawSqlMigration
)
.
Sqlite
(
`
Sqlite
(
`
CREATE TABLE account (
CREATE TABLE account (
id INTEGER PRIMARY KEY AUTOINCREMENT,
id INTEGER PRIMARY KEY AUTOINCREMENT,
...
@@ -34,25 +36,18 @@ func init() {
...
@@ -34,25 +36,18 @@ func init() {
)
)
`
))
`
))
// ------------------------------
// ------------------------------
addMigration
(
new
(
AddIndexMigration
)
.
mg
.
AddMigration
(
"add index UIX_account.login"
,
new
(
AddIndexMigration
)
.
Name
(
"UIX_account_login"
)
.
Table
(
"account"
)
.
Columns
(
"login"
))
Name
(
"UIX_account_login"
)
.
Table
(
"account"
)
.
Columns
(
"login"
))
// ------------------------------
// ------------------------------
addMigration
(
new
(
AddColumnMigration
)
.
Desc
(
"Add name column"
)
.
mg
.
AddMigration
(
"add column"
,
new
(
AddColumnMigration
)
.
Table
(
"account"
)
.
Column
(
"name"
)
.
Type
(
DB_TYPE_STRING
)
.
Length
(
255
))
Table
(
"account"
)
.
Column
(
"name"
)
.
Type
(
DB_TYPE_STRING
)
.
Length
(
255
))
}
}
func
addMigration
(
m
Migration
)
{
type
MigrationLog
struct
{
migrationList
=
append
(
migrationList
,
m
)
Id
int64
}
MigrationId
string
Sql
string
type
SchemaVersion
struct
{
Success
bool
Version
int
Error
string
}
Timestamp
time
.
Time
type
SchemaLog
struct
{
Id
int64
Version
int64
Desc
string
Info
string
Error
bool
}
}
pkg/services/sqlstore/migrations/migrations_test.go
View file @
a64a38d7
...
@@ -6,6 +6,7 @@ import (
...
@@ -6,6 +6,7 @@ import (
"testing"
"testing"
"github.com/go-xorm/xorm"
"github.com/go-xorm/xorm"
"github.com/torkelo/grafana-pro/pkg/log"
.
"github.com/smartystreets/goconvey/convey"
.
"github.com/smartystreets/goconvey/convey"
)
)
...
@@ -31,8 +32,10 @@ func cleanDB(x *xorm.Engine) {
...
@@ -31,8 +32,10 @@ func cleanDB(x *xorm.Engine) {
var
indexTypes
=
[]
string
{
"Unknown"
,
""
,
"UNIQUE"
}
var
indexTypes
=
[]
string
{
"Unknown"
,
""
,
"UNIQUE"
}
func
TestMigrations
(
t
*
testing
.
T
)
{
func
TestMigrations
(
t
*
testing
.
T
)
{
log
.
NewLogger
(
0
,
"console"
,
`{"level": 0}`
)
testDBs
:=
[][]
string
{
testDBs
:=
[][]
string
{
//
[]string{"mysql", "grafana:password@tcp(localhost:3306)/grafana_tests?charset=utf8"},
[]
string
{
"mysql"
,
"grafana:password@tcp(localhost:3306)/grafana_tests?charset=utf8"
},
[]
string
{
"sqlite3"
,
":memory:"
},
[]
string
{
"sqlite3"
,
":memory:"
},
}
}
...
@@ -46,7 +49,10 @@ func TestMigrations(t *testing.T) {
...
@@ -46,7 +49,10 @@ func TestMigrations(t *testing.T) {
cleanDB
(
x
)
cleanDB
(
x
)
}
}
err
=
StartMigration
(
x
)
mg
:=
NewMigrator
(
x
)
AddMigrations
(
mg
)
err
=
mg
.
Start
()
So
(
err
,
ShouldBeNil
)
So
(
err
,
ShouldBeNil
)
tables
,
err
:=
x
.
DBMetas
()
tables
,
err
:=
x
.
DBMetas
()
...
...
pkg/services/sqlstore/migrations/
engine
.go
→
pkg/services/sqlstore/migrations/
migrator
.go
View file @
a64a38d7
package
migrations
package
migrations
import
(
import
(
"time"
_
"github.com/go-sql-driver/mysql"
_
"github.com/go-sql-driver/mysql"
"github.com/go-xorm/xorm"
"github.com/go-xorm/xorm"
_
"github.com/lib/pq"
_
"github.com/lib/pq"
...
@@ -8,60 +10,102 @@ import (
...
@@ -8,60 +10,102 @@ import (
"github.com/torkelo/grafana-pro/pkg/log"
"github.com/torkelo/grafana-pro/pkg/log"
)
)
var
x
*
xorm
.
Engine
type
Migrator
struct
{
var
dialect
Dialect
x
*
xorm
.
Engine
dialect
Dialect
migrations
[]
Migration
}
func
NewMigrator
(
engine
*
xorm
.
Engine
)
*
Migrator
{
mg
:=
&
Migrator
{}
mg
.
x
=
engine
mg
.
migrations
=
make
([]
Migration
,
0
)
switch
mg
.
x
.
DriverName
()
{
case
MYSQL
:
mg
.
dialect
=
new
(
Mysql
)
case
SQLITE
:
mg
.
dialect
=
new
(
Sqlite3
)
}
return
mg
}
func
(
mg
*
Migrator
)
AddMigration
(
id
string
,
m
Migration
)
{
m
.
SetId
(
id
)
mg
.
migrations
=
append
(
mg
.
migrations
,
m
)
}
func
getSchemaVersion
()
(
int
,
error
)
{
func
(
mg
*
Migrator
)
GetMigrationLog
()
(
map
[
string
]
MigrationLog
,
error
)
{
exists
,
err
:=
x
.
IsTableExist
(
new
(
SchemaVersion
))
exists
,
err
:=
mg
.
x
.
IsTableExist
(
new
(
MigrationLog
))
if
err
!=
nil
{
if
err
!=
nil
{
return
0
,
err
return
nil
,
err
}
}
if
!
exists
{
if
!
exists
{
if
err
:=
x
.
CreateTables
(
new
(
SchemaVersion
));
err
!=
nil
{
if
err
:=
mg
.
x
.
CreateTables
(
new
(
MigrationLog
));
err
!=
nil
{
return
0
,
err
return
nil
,
err
}
}
return
0
,
nil
return
nil
,
nil
}
}
v
:=
SchemaVersion
{}
logMap
:=
make
(
map
[
string
]
MigrationLog
)
_
,
err
=
x
.
Table
(
"schema_version"
)
.
Limit
(
1
,
0
)
.
Desc
(
"version"
)
.
Get
(
&
v
)
logItems
:=
make
([]
MigrationLog
,
0
)
return
v
.
Version
,
err
if
err
=
mg
.
x
.
Find
(
&
logItems
);
err
!=
nil
{
}
return
nil
,
err
}
func
setEngineAndDialect
(
engine
*
xorm
.
Engine
)
{
for
_
,
logItem
:=
range
logItems
{
x
=
engine
if
!
logItem
.
Success
{
switch
x
.
DriverName
()
{
continue
case
MYSQL
:
}
dialect
=
new
(
Mysql
)
logMap
[
logItem
.
MigrationId
]
=
logItem
case
SQLITE
:
dialect
=
new
(
Sqlite3
)
}
}
}
func
StartMigration
(
engine
*
xorm
.
Engine
)
error
{
return
logMap
,
nil
log
.
Info
(
"Starting database schema migration: DB: %v"
,
engine
.
DriverName
())
}
setEngineAndDialect
(
engine
)
func
(
mg
*
Migrator
)
Start
()
error
{
log
.
Info
(
"Migrator::Start DB migration"
)
_
,
err
:=
getSchemaVersion
()
logMap
,
err
:=
mg
.
GetMigrationLog
()
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
for
_
,
m
:=
range
migrationList
{
for
_
,
m
:=
range
mg
.
migrations
{
if
err
:=
execMigration
(
m
);
err
!=
nil
{
_
,
exists
:=
logMap
[
m
.
Id
()]
if
exists
{
log
.
Info
(
"Migrator:: Skipping migration: %v, Already executed"
,
m
.
Id
())
continue
}
record
:=
MigrationLog
{
MigrationId
:
m
.
Id
(),
Sql
:
m
.
Sql
(
mg
.
dialect
),
Timestamp
:
time
.
Now
(),
}
if
err
:=
mg
.
exec
(
m
);
err
!=
nil
{
record
.
Error
=
err
.
Error
()
mg
.
x
.
Insert
(
&
record
)
return
err
return
err
}
else
{
record
.
Success
=
true
mg
.
x
.
Insert
(
&
record
)
}
}
}
}
return
nil
return
nil
}
}
func
execMigration
(
m
Migration
)
error
{
func
(
mg
*
Migrator
)
exec
(
m
Migration
)
error
{
err
:=
inTransaction
(
func
(
sess
*
xorm
.
Session
)
error
{
log
.
Info
(
"Migrator::exec migration id: %v"
,
m
.
Id
())
_
,
err
:=
sess
.
Exec
(
m
.
Sql
(
dialect
))
err
:=
mg
.
inTransaction
(
func
(
sess
*
xorm
.
Session
)
error
{
_
,
err
:=
sess
.
Exec
(
m
.
Sql
(
mg
.
dialect
))
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Error
(
3
,
"Migrator::exec FAILED migration id: %v, err: %v"
,
m
.
Id
(),
err
)
return
err
return
err
}
}
return
nil
return
nil
...
@@ -76,10 +120,10 @@ func execMigration(m Migration) error {
...
@@ -76,10 +120,10 @@ func execMigration(m Migration) error {
type
dbTransactionFunc
func
(
sess
*
xorm
.
Session
)
error
type
dbTransactionFunc
func
(
sess
*
xorm
.
Session
)
error
func
inTransaction
(
callback
dbTransactionFunc
)
error
{
func
(
mg
*
Migrator
)
inTransaction
(
callback
dbTransactionFunc
)
error
{
var
err
error
var
err
error
sess
:=
x
.
NewSession
()
sess
:=
mg
.
x
.
NewSession
()
defer
sess
.
Close
()
defer
sess
.
Close
()
if
err
=
sess
.
Begin
();
err
!=
nil
{
if
err
=
sess
.
Begin
();
err
!=
nil
{
...
...
pkg/services/sqlstore/migrations/migrator_test.go
0 → 100644
View file @
a64a38d7
package
migrations
import
(
"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")
// }
// }
// }
//
// var indexTypes = []string{"Unknown", "", "UNIQUE"}
//
func
TestMigrator
(
t
*
testing
.
T
)
{
Convey
(
"Migrator"
,
t
,
func
()
{
x
,
err
:=
xorm
.
NewEngine
(
SQLITE
,
":memory:"
)
So
(
err
,
ShouldBeNil
)
mg
:=
NewMigrator
(
x
)
Convey
(
"Given one migration"
,
func
()
{
mg
.
AddMigration
(
"test migration"
,
new
(
RawSqlMigration
)
.
Sqlite
(
`
CREATE TABLE account (
id INTEGER PRIMARY KEY AUTOINCREMENT
)`
)
.
Mysql
(
`
CREATE TABLE account (
id BIGINT NOT NULL AUTO_INCREMENT, PRIMARY KEY (id)
)`
))
err
:=
mg
.
Start
()
So
(
err
,
ShouldBeNil
)
log
,
err
:=
mg
.
GetMigrationLog
()
So
(
err
,
ShouldBeNil
)
So
(
len
(
log
),
ShouldEqual
,
1
)
})
// So(err, ShouldBeNil)
//
// So(len(tables), ShouldEqual, 2)
// fmt.Printf("\nDB Schema after migration: table count: %v\n", len(tables))
//
// for _, table := range tables {
// fmt.Printf("\nTable: %v \n", table.Name)
// for _, column := range table.Columns() {
// fmt.Printf("\t %v \n", column.String(x.Dialect()))
// }
//
// if len(table.Indexes) > 0 {
// fmt.Printf("\n\tIndexes:\n")
// for _, index := range table.Indexes {
// fmt.Printf("\t %v (%v) %v \n", index.Name, strings.Join(index.Cols, ","), indexTypes[index.Type])
// }
// }
// }
})
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment