shell.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. // Copyright 2017 The Xorm Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package main
  5. import (
  6. "fmt"
  7. "strings"
  8. "github.com/go-xorm/core"
  9. "github.com/go-xorm/xorm"
  10. )
  11. var CmdShell = &Command{
  12. UsageLine: "shell driverName datasourceName",
  13. Short: "a general shell to operate all kinds of database",
  14. Long: `
  15. general database's shell for sqlite3, mysql, postgres.
  16. driverName Database driver name, now supported four: mysql mymysql sqlite3 postgres
  17. datasourceName Database connection uri, for detail infomation please visit driver's project page
  18. `,
  19. }
  20. func init() {
  21. CmdShell.Run = runShell
  22. CmdShell.Flags = map[string]bool{}
  23. }
  24. var engine *xorm.Engine
  25. func shellHelp() {
  26. fmt.Println(`
  27. show tables show all tables
  28. columns <table_name> show table's column info
  29. indexes <table_name> show table's index info
  30. exit exit shell
  31. source <sql_file> exec sql file to current database
  32. dump [-nodata] <sql_file> dump structs or records to sql file
  33. help show this document
  34. <statement> SQL statement
  35. `)
  36. }
  37. func runShell(cmd *Command, args []string) {
  38. if len(args) != 2 {
  39. fmt.Println("params error, please see xorm help shell")
  40. return
  41. }
  42. var err error
  43. engine, err = xorm.NewEngine(args[0], args[1])
  44. if err != nil {
  45. fmt.Println(err)
  46. return
  47. }
  48. engine.ShowSQL(false)
  49. engine.Logger().SetLevel(core.LOG_UNKNOWN)
  50. err = engine.Ping()
  51. if err != nil {
  52. fmt.Println(err)
  53. return
  54. }
  55. var scmd string
  56. fmt.Print("xorm$ ")
  57. for {
  58. var input string
  59. _, err := fmt.Scan(&input)
  60. if err != nil {
  61. fmt.Println(err)
  62. continue
  63. }
  64. if strings.ToLower(input) == "help" {
  65. shellHelp()
  66. scmd = ""
  67. fmt.Print("xorm$ ")
  68. continue
  69. }
  70. if strings.ToLower(input) == "exit" {
  71. fmt.Println("bye")
  72. return
  73. }
  74. if !strings.HasSuffix(input, ";") {
  75. scmd = scmd + " " + input
  76. continue
  77. }
  78. scmd = scmd + " " + input
  79. lcmd := strings.TrimSpace(strings.ToLower(scmd))
  80. lcmd = strings.TrimRight(lcmd, ";")
  81. if strings.HasPrefix(lcmd, "select") {
  82. res, err := engine.Query(scmd + "\n")
  83. if err != nil {
  84. fmt.Println(err)
  85. } else {
  86. if len(res) <= 0 {
  87. fmt.Println("no records")
  88. } else {
  89. columns := make(map[string]int)
  90. for k, _ := range res[0] {
  91. columns[k] = len(k)
  92. }
  93. for _, m := range res {
  94. for k, s := range m {
  95. l := len(string(s))
  96. if l > columns[k] {
  97. columns[k] = l
  98. }
  99. }
  100. }
  101. var maxlen = 0
  102. for _, l := range columns {
  103. maxlen = maxlen + l + 3
  104. }
  105. maxlen = maxlen + 1
  106. fmt.Println(strings.Repeat("-", maxlen))
  107. fmt.Print("|")
  108. slice := make([]string, 0)
  109. for k, l := range columns {
  110. fmt.Print(" " + k + " ")
  111. fmt.Print(strings.Repeat(" ", l-len(k)))
  112. fmt.Print("|")
  113. slice = append(slice, k)
  114. }
  115. fmt.Print("\n")
  116. for _, r := range res {
  117. fmt.Print("|")
  118. for _, k := range slice {
  119. fmt.Print(" " + string(r[k]) + " ")
  120. fmt.Print(strings.Repeat(" ", columns[k]-len(string(r[k]))))
  121. fmt.Print("|")
  122. }
  123. fmt.Print("\n")
  124. }
  125. fmt.Println(strings.Repeat("-", maxlen))
  126. //fmt.Println(res)
  127. }
  128. }
  129. } else if lcmd == "show tables" {
  130. tables, err := engine.Dialect().GetTables()
  131. if err != nil {
  132. fmt.Println(err)
  133. } else {
  134. var maxlen int
  135. for _, table := range tables {
  136. if len(table.Name) > maxlen {
  137. maxlen = len(table.Name)
  138. }
  139. }
  140. head := "Table Name"
  141. if maxlen < len(head) {
  142. maxlen = len(head)
  143. }
  144. maxlen = maxlen + 2
  145. fmt.Println(strings.Repeat("-", maxlen+3))
  146. fmt.Print("| " + head + strings.Repeat(" ", maxlen-len(head)))
  147. fmt.Println("|")
  148. fmt.Println(strings.Repeat("-", maxlen+3))
  149. for _, table := range tables {
  150. fmt.Print("|")
  151. fmt.Print(" " + table.Name)
  152. fmt.Print(strings.Repeat(" ", maxlen-len(table.Name)))
  153. fmt.Println("|")
  154. }
  155. fmt.Println(strings.Repeat("-", maxlen+3))
  156. }
  157. } else if strings.HasPrefix(lcmd, "dump") {
  158. fields := strings.Fields(strings.TrimRight(scmd, ";"))
  159. if len(fields) == 2 {
  160. err = engine.DumpAllToFile(fields[1])
  161. if err != nil {
  162. fmt.Println(err)
  163. } else {
  164. fmt.Println("dump successfully!")
  165. }
  166. } else {
  167. fmt.Println("param error")
  168. }
  169. } else if strings.HasPrefix(lcmd, "source") {
  170. fields := strings.Fields(strings.TrimRight(scmd, ";"))
  171. if len(fields) == 2 {
  172. _, err = engine.ImportFile(fields[1])
  173. if err.Error() == "not an error" {
  174. err = nil
  175. }
  176. if err != nil {
  177. fmt.Println(err)
  178. }
  179. } else {
  180. fmt.Println("param error")
  181. }
  182. } else if strings.HasPrefix(lcmd, "columns") {
  183. fields := strings.Fields(strings.TrimRight(scmd, ";"))
  184. if len(fields) == 2 {
  185. _, columns, err := engine.Dialect().GetColumns(fields[1])
  186. if err != nil {
  187. fmt.Println(err)
  188. } else {
  189. if len(columns) == 0 {
  190. fmt.Println("no column in", fields[1])
  191. } else {
  192. var maxlen int
  193. for name, _ := range columns {
  194. if len(name) > maxlen {
  195. maxlen = len(name)
  196. }
  197. }
  198. head := "Column Name"
  199. if maxlen < len(head) {
  200. maxlen = len(head)
  201. }
  202. maxlen = maxlen + 2
  203. fmt.Println(strings.Repeat("-", maxlen+3))
  204. fmt.Print("| " + head + strings.Repeat(" ", maxlen-len(head)))
  205. fmt.Println("|")
  206. fmt.Println(strings.Repeat("-", maxlen+3))
  207. for name, _ := range columns {
  208. fmt.Print("|")
  209. fmt.Print(" " + name)
  210. fmt.Print(strings.Repeat(" ", maxlen-len(name)))
  211. fmt.Println("|")
  212. }
  213. fmt.Println(strings.Repeat("-", maxlen+3))
  214. }
  215. }
  216. } else {
  217. fmt.Println("param error")
  218. }
  219. } else if strings.HasPrefix(lcmd, "indexes") {
  220. fields := strings.Fields(strings.TrimRight(scmd, ";"))
  221. if len(fields) == 2 {
  222. indexes, err := engine.Dialect().GetIndexes(fields[1])
  223. if err != nil {
  224. fmt.Println(err)
  225. } else {
  226. if len(indexes) == 0 {
  227. fmt.Println("no index in", fields[1])
  228. } else {
  229. var maxlen int
  230. for name, _ := range indexes {
  231. if len(name) > maxlen {
  232. maxlen = len(name)
  233. }
  234. }
  235. head := "Index Name"
  236. if maxlen < len(head) {
  237. maxlen = len(head)
  238. }
  239. maxlen = maxlen + 2
  240. fmt.Println(strings.Repeat("-", maxlen+3))
  241. fmt.Print("| " + head + strings.Repeat(" ", maxlen-len(head)))
  242. fmt.Println("|")
  243. fmt.Println(strings.Repeat("-", maxlen+3))
  244. for name, _ := range indexes {
  245. fmt.Print("|")
  246. fmt.Print(" " + name)
  247. fmt.Print(strings.Repeat(" ", maxlen-len(name)))
  248. fmt.Println("|")
  249. }
  250. fmt.Println(strings.Repeat("-", maxlen+3))
  251. }
  252. }
  253. } else {
  254. fmt.Println("param error")
  255. }
  256. } else {
  257. res, err := engine.Exec(scmd)
  258. if err != nil {
  259. fmt.Println(err)
  260. } else {
  261. cnt, err := res.RowsAffected()
  262. if err != nil {
  263. fmt.Println(err)
  264. } else {
  265. fmt.Printf("%d records changed.\n", cnt)
  266. }
  267. }
  268. }
  269. scmd = ""
  270. fmt.Print("xorm$ ")
  271. }
  272. }