migration: version 1
Showing
1 changed file
with
187 additions
and
0 deletions
migration/migration.go
0 → 100644
| 1 | // Beego (http://beego.me/) | ||
| 2 | // | ||
| 3 | // @description beego is an open-source, high-performance web framework for the Go programming language. | ||
| 4 | // | ||
| 5 | // @link http://github.com/astaxie/beego for the canonical source repository | ||
| 6 | // | ||
| 7 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | ||
| 8 | // | ||
| 9 | // @authors astaxie | ||
| 10 | package migration | ||
| 11 | |||
| 12 | import ( | ||
| 13 | "errors" | ||
| 14 | "sort" | ||
| 15 | "time" | ||
| 16 | |||
| 17 | "github.com/astaxie/beego" | ||
| 18 | "github.com/astaxie/beego/orm" | ||
| 19 | ) | ||
| 20 | |||
| 21 | // const the data format for the bee generate migration datatype | ||
| 22 | const M_DATE_FORMAT = "20060102_150405" | ||
| 23 | |||
| 24 | // Migrationer is an interface for all Migration struct | ||
| 25 | type Migrationer interface { | ||
| 26 | Up() | ||
| 27 | Down() | ||
| 28 | Exec() error | ||
| 29 | GetCreated() int64 | ||
| 30 | } | ||
| 31 | |||
| 32 | var migrationMap map[string]Migrationer | ||
| 33 | |||
| 34 | func init() { | ||
| 35 | migrationMap = make(map[string]Migrationer) | ||
| 36 | } | ||
| 37 | |||
| 38 | // the basic type which will implement the basic type | ||
| 39 | type Migration struct { | ||
| 40 | sqls []string | ||
| 41 | Created string | ||
| 42 | } | ||
| 43 | |||
| 44 | // implement in the Inheritance struct for upgrade | ||
| 45 | func (m *Migration) Up() { | ||
| 46 | |||
| 47 | } | ||
| 48 | |||
| 49 | // implement in the Inheritance struct for down | ||
| 50 | func (m *Migration) Down() { | ||
| 51 | |||
| 52 | } | ||
| 53 | |||
| 54 | // add sql want to execute | ||
| 55 | func (m *Migration) Sql(sql string) { | ||
| 56 | m.sqls = append(m.sqls, sql) | ||
| 57 | } | ||
| 58 | |||
| 59 | // execute the sql already add in the sql | ||
| 60 | func (m *Migration) Exec() error { | ||
| 61 | o := orm.NewOrm() | ||
| 62 | for _, s := range m.sqls { | ||
| 63 | beego.Info("exec sql:", s) | ||
| 64 | r := o.Raw(s) | ||
| 65 | _, err := r.Exec() | ||
| 66 | if err != nil { | ||
| 67 | return err | ||
| 68 | } | ||
| 69 | } | ||
| 70 | return nil | ||
| 71 | } | ||
| 72 | |||
| 73 | // get the unixtime from the Created | ||
| 74 | func (m *Migration) GetCreated() int64 { | ||
| 75 | t, err := time.Parse(M_DATE_FORMAT, m.Created) | ||
| 76 | if err != nil { | ||
| 77 | return 0 | ||
| 78 | } | ||
| 79 | return t.Unix() | ||
| 80 | } | ||
| 81 | |||
| 82 | // register the Migration in the map | ||
| 83 | func Register(name string, m Migrationer) error { | ||
| 84 | if _, ok := migrationMap[name]; ok { | ||
| 85 | return errors.New("already exist name:" + name) | ||
| 86 | } | ||
| 87 | migrationMap[name] = m | ||
| 88 | return nil | ||
| 89 | } | ||
| 90 | |||
| 91 | // upgrate the migration from lasttime | ||
| 92 | func Upgrade(lasttime int64) error { | ||
| 93 | sm := sortMap(migrationMap) | ||
| 94 | i := 0 | ||
| 95 | for _, v := range sm { | ||
| 96 | if v.created > lasttime { | ||
| 97 | beego.Info("start upgrade", v.name) | ||
| 98 | v.m.Up() | ||
| 99 | err := v.m.Exec() | ||
| 100 | if err != nil { | ||
| 101 | return err | ||
| 102 | } | ||
| 103 | beego.Info("end upgrade:", v.name) | ||
| 104 | i++ | ||
| 105 | } | ||
| 106 | } | ||
| 107 | beego.Info("total success upgrade:", i, " migration") | ||
| 108 | return nil | ||
| 109 | } | ||
| 110 | |||
| 111 | //rollback the migration by the name | ||
| 112 | func Rollback(name string) error { | ||
| 113 | if v, ok := migrationMap[name]; ok { | ||
| 114 | beego.Info("start rollback") | ||
| 115 | v.Down() | ||
| 116 | err := v.Exec() | ||
| 117 | if err != nil { | ||
| 118 | return err | ||
| 119 | } | ||
| 120 | beego.Info("end rollback") | ||
| 121 | return nil | ||
| 122 | } else { | ||
| 123 | return errors.New("not exist the migrationMap name:" + name) | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 127 | // reset all migration | ||
| 128 | // run all migration's down function | ||
| 129 | func Reset() error { | ||
| 130 | i := 0 | ||
| 131 | for k, v := range migrationMap { | ||
| 132 | beego.Info("start reset:", k) | ||
| 133 | v.Down() | ||
| 134 | err := v.Exec() | ||
| 135 | if err != nil { | ||
| 136 | return err | ||
| 137 | } | ||
| 138 | beego.Info("end reset:", k) | ||
| 139 | } | ||
| 140 | beego.Info("total success reset:", i, " migration") | ||
| 141 | return nil | ||
| 142 | } | ||
| 143 | |||
| 144 | // first Reset, then Upgrade | ||
| 145 | func Refresh() error { | ||
| 146 | err := Reset() | ||
| 147 | if err != nil { | ||
| 148 | return err | ||
| 149 | } | ||
| 150 | return Upgrade(0) | ||
| 151 | } | ||
| 152 | |||
| 153 | type dataSlice []data | ||
| 154 | |||
| 155 | type data struct { | ||
| 156 | created int64 | ||
| 157 | name string | ||
| 158 | m Migrationer | ||
| 159 | } | ||
| 160 | |||
| 161 | // Len is part of sort.Interface. | ||
| 162 | func (d dataSlice) Len() int { | ||
| 163 | return len(d) | ||
| 164 | } | ||
| 165 | |||
| 166 | // Swap is part of sort.Interface. | ||
| 167 | func (d dataSlice) Swap(i, j int) { | ||
| 168 | d[i], d[j] = d[j], d[i] | ||
| 169 | } | ||
| 170 | |||
| 171 | // Less is part of sort.Interface. We use count as the value to sort by | ||
| 172 | func (d dataSlice) Less(i, j int) bool { | ||
| 173 | return d[i].created < d[j].created | ||
| 174 | } | ||
| 175 | |||
| 176 | func sortMap(m map[string]Migrationer) dataSlice { | ||
| 177 | s := make(dataSlice, 0, len(m)) | ||
| 178 | for k, v := range m { | ||
| 179 | d := data{} | ||
| 180 | d.created = v.GetCreated() | ||
| 181 | d.name = k | ||
| 182 | d.m = v | ||
| 183 | s = append(s, d) | ||
| 184 | } | ||
| 185 | sort.Sort(s) | ||
| 186 | return s | ||
| 187 | } |
-
Please register or sign in to post a comment