1
0

cmd.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. // Copyright 2014 beego Author. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package orm
  15. import (
  16. "flag"
  17. "fmt"
  18. "os"
  19. "strings"
  20. )
  21. type commander interface {
  22. Parse([]string)
  23. Run() error
  24. }
  25. var (
  26. commands = make(map[string]commander)
  27. )
  28. // print help.
  29. func printHelp(errs ...string) {
  30. content := `orm command usage:
  31. syncdb - auto create tables
  32. sqlall - print sql of create tables
  33. help - print this help
  34. `
  35. if len(errs) > 0 {
  36. fmt.Println(errs[0])
  37. }
  38. fmt.Println(content)
  39. os.Exit(2)
  40. }
  41. // RunCommand listen for orm command and then run it if command arguments passed.
  42. func RunCommand() {
  43. if len(os.Args) < 2 || os.Args[1] != "orm" {
  44. return
  45. }
  46. BootStrap()
  47. args := argString(os.Args[2:])
  48. name := args.Get(0)
  49. if name == "help" {
  50. printHelp()
  51. }
  52. if cmd, ok := commands[name]; ok {
  53. cmd.Parse(os.Args[3:])
  54. cmd.Run()
  55. os.Exit(0)
  56. } else {
  57. if name == "" {
  58. printHelp()
  59. } else {
  60. printHelp(fmt.Sprintf("unknown command %s", name))
  61. }
  62. }
  63. }
  64. // sync database struct command interface.
  65. type commandSyncDb struct {
  66. al *alias
  67. force bool
  68. verbose bool
  69. noInfo bool
  70. rtOnError bool
  71. }
  72. // parse orm command line arguments.
  73. func (d *commandSyncDb) Parse(args []string) {
  74. var name string
  75. flagSet := flag.NewFlagSet("orm command: syncdb", flag.ExitOnError)
  76. flagSet.StringVar(&name, "db", "default", "DataBase alias name")
  77. flagSet.BoolVar(&d.force, "force", false, "drop tables before create")
  78. flagSet.BoolVar(&d.verbose, "v", false, "verbose info")
  79. flagSet.Parse(args)
  80. d.al = getDbAlias(name)
  81. }
  82. // run orm line command.
  83. func (d *commandSyncDb) Run() error {
  84. var drops []string
  85. if d.force {
  86. drops = getDbDropSQL(d.al)
  87. }
  88. db := d.al.DB
  89. if d.force {
  90. for i, mi := range modelCache.allOrdered() {
  91. query := drops[i]
  92. if !d.noInfo {
  93. fmt.Printf("drop table `%s`\n", mi.table)
  94. }
  95. _, err := db.Exec(query)
  96. if d.verbose {
  97. fmt.Printf(" %s\n\n", query)
  98. }
  99. if err != nil {
  100. if d.rtOnError {
  101. return err
  102. }
  103. fmt.Printf(" %s\n", err.Error())
  104. }
  105. }
  106. }
  107. sqls, indexes := getDbCreateSQL(d.al)
  108. tables, err := d.al.DbBaser.GetTables(db)
  109. if err != nil {
  110. if d.rtOnError {
  111. return err
  112. }
  113. fmt.Printf(" %s\n", err.Error())
  114. }
  115. for i, mi := range modelCache.allOrdered() {
  116. if tables[mi.table] {
  117. if !d.noInfo {
  118. fmt.Printf("table `%s` already exists, skip\n", mi.table)
  119. }
  120. var fields []*fieldInfo
  121. columns, err := d.al.DbBaser.GetColumns(db, mi.table)
  122. if err != nil {
  123. if d.rtOnError {
  124. return err
  125. }
  126. fmt.Printf(" %s\n", err.Error())
  127. }
  128. for _, fi := range mi.fields.fieldsDB {
  129. if _, ok := columns[fi.column]; ok == false {
  130. fields = append(fields, fi)
  131. }
  132. }
  133. for _, fi := range fields {
  134. query := getColumnAddQuery(d.al, fi)
  135. if !d.noInfo {
  136. fmt.Printf("add column `%s` for table `%s`\n", fi.fullName, mi.table)
  137. }
  138. _, err := db.Exec(query)
  139. if d.verbose {
  140. fmt.Printf(" %s\n", query)
  141. }
  142. if err != nil {
  143. if d.rtOnError {
  144. return err
  145. }
  146. fmt.Printf(" %s\n", err.Error())
  147. }
  148. }
  149. for _, idx := range indexes[mi.table] {
  150. if d.al.DbBaser.IndexExists(db, idx.Table, idx.Name) == false {
  151. if !d.noInfo {
  152. fmt.Printf("create index `%s` for table `%s`\n", idx.Name, idx.Table)
  153. }
  154. query := idx.SQL
  155. _, err := db.Exec(query)
  156. if d.verbose {
  157. fmt.Printf(" %s\n", query)
  158. }
  159. if err != nil {
  160. if d.rtOnError {
  161. return err
  162. }
  163. fmt.Printf(" %s\n", err.Error())
  164. }
  165. }
  166. }
  167. continue
  168. }
  169. if !d.noInfo {
  170. fmt.Printf("create table `%s` \n", mi.table)
  171. }
  172. queries := []string{sqls[i]}
  173. for _, idx := range indexes[mi.table] {
  174. queries = append(queries, idx.SQL)
  175. }
  176. for _, query := range queries {
  177. _, err := db.Exec(query)
  178. if d.verbose {
  179. query = " " + strings.Join(strings.Split(query, "\n"), "\n ")
  180. fmt.Println(query)
  181. }
  182. if err != nil {
  183. if d.rtOnError {
  184. return err
  185. }
  186. fmt.Printf(" %s\n", err.Error())
  187. }
  188. }
  189. if d.verbose {
  190. fmt.Println("")
  191. }
  192. }
  193. return nil
  194. }
  195. // database creation commander interface implement.
  196. type commandSQLAll struct {
  197. al *alias
  198. }
  199. // parse orm command line arguments.
  200. func (d *commandSQLAll) Parse(args []string) {
  201. var name string
  202. flagSet := flag.NewFlagSet("orm command: sqlall", flag.ExitOnError)
  203. flagSet.StringVar(&name, "db", "default", "DataBase alias name")
  204. flagSet.Parse(args)
  205. d.al = getDbAlias(name)
  206. }
  207. // run orm line command.
  208. func (d *commandSQLAll) Run() error {
  209. sqls, indexes := getDbCreateSQL(d.al)
  210. var all []string
  211. for i, mi := range modelCache.allOrdered() {
  212. queries := []string{sqls[i]}
  213. for _, idx := range indexes[mi.table] {
  214. queries = append(queries, idx.SQL)
  215. }
  216. sql := strings.Join(queries, "\n")
  217. all = append(all, sql)
  218. }
  219. fmt.Println(strings.Join(all, "\n\n"))
  220. return nil
  221. }
  222. func init() {
  223. commands["syncdb"] = new(commandSyncDb)
  224. commands["sqlall"] = new(commandSQLAll)
  225. }
  226. // RunSyncdb run syncdb command line.
  227. // name means table's alias name. default is "default".
  228. // force means run next sql if the current is error.
  229. // verbose means show all info when running command or not.
  230. func RunSyncdb(name string, force bool, verbose bool) error {
  231. BootStrap()
  232. al := getDbAlias(name)
  233. cmd := new(commandSyncDb)
  234. cmd.al = al
  235. cmd.force = force
  236. cmd.noInfo = !verbose
  237. cmd.verbose = verbose
  238. cmd.rtOnError = true
  239. return cmd.Run()
  240. }