command.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. package command
  2. import (
  3. "errors"
  4. "path/filepath"
  5. "strings"
  6. "github.com/go-sql-driver/mysql"
  7. "github.com/urfave/cli"
  8. "github.com/zeromicro/go-zero/core/logx"
  9. "github.com/zeromicro/go-zero/core/stores/postgres"
  10. "github.com/zeromicro/go-zero/core/stores/sqlx"
  11. "github.com/zeromicro/go-zero/tools/goctl/config"
  12. "github.com/zeromicro/go-zero/tools/goctl/model/sql/command/migrationnotes"
  13. "github.com/zeromicro/go-zero/tools/goctl/model/sql/gen"
  14. "github.com/zeromicro/go-zero/tools/goctl/model/sql/model"
  15. "github.com/zeromicro/go-zero/tools/goctl/model/sql/util"
  16. file "github.com/zeromicro/go-zero/tools/goctl/util"
  17. "github.com/zeromicro/go-zero/tools/goctl/util/console"
  18. "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
  19. )
  20. const (
  21. flagSrc = "src"
  22. flagDir = "dir"
  23. flagCache = "cache"
  24. flagIdea = "idea"
  25. flagURL = "url"
  26. flagTable = "table"
  27. flagStyle = "style"
  28. flagDatabase = "database"
  29. flagSchema = "schema"
  30. flagHome = "home"
  31. flagRemote = "remote"
  32. flagBranch = "branch"
  33. )
  34. var errNotMatched = errors.New("sql not matched")
  35. // MysqlDDL generates model code from ddl
  36. func MysqlDDL(ctx *cli.Context) error {
  37. migrationnotes.BeforeCommands(ctx)
  38. src := ctx.String(flagSrc)
  39. dir := ctx.String(flagDir)
  40. cache := ctx.Bool(flagCache)
  41. idea := ctx.Bool(flagIdea)
  42. style := ctx.String(flagStyle)
  43. database := ctx.String(flagDatabase)
  44. home := ctx.String(flagHome)
  45. remote := ctx.String(flagRemote)
  46. branch := ctx.String(flagBranch)
  47. if len(remote) > 0 {
  48. repo, _ := file.CloneIntoGitHome(remote, branch)
  49. if len(repo) > 0 {
  50. home = repo
  51. }
  52. }
  53. if len(home) > 0 {
  54. pathx.RegisterGoctlHome(home)
  55. }
  56. cfg, err := config.NewConfig(style)
  57. if err != nil {
  58. return err
  59. }
  60. return fromDDL(src, dir, cfg, cache, idea, database)
  61. }
  62. // MySqlDataSource generates model code from datasource
  63. func MySqlDataSource(ctx *cli.Context) error {
  64. migrationnotes.BeforeCommands(ctx)
  65. url := strings.TrimSpace(ctx.String(flagURL))
  66. dir := strings.TrimSpace(ctx.String(flagDir))
  67. cache := ctx.Bool(flagCache)
  68. idea := ctx.Bool(flagIdea)
  69. style := ctx.String(flagStyle)
  70. home := ctx.String(flagHome)
  71. remote := ctx.String(flagRemote)
  72. branch := ctx.String(flagBranch)
  73. if len(remote) > 0 {
  74. repo, _ := file.CloneIntoGitHome(remote, branch)
  75. if len(repo) > 0 {
  76. home = repo
  77. }
  78. }
  79. if len(home) > 0 {
  80. pathx.RegisterGoctlHome(home)
  81. }
  82. pattern := strings.TrimSpace(ctx.String(flagTable))
  83. cfg, err := config.NewConfig(style)
  84. if err != nil {
  85. return err
  86. }
  87. return fromMysqlDataSource(url, pattern, dir, cfg, cache, idea)
  88. }
  89. // PostgreSqlDataSource generates model code from datasource
  90. func PostgreSqlDataSource(ctx *cli.Context) error {
  91. migrationnotes.BeforeCommands(ctx)
  92. url := strings.TrimSpace(ctx.String(flagURL))
  93. dir := strings.TrimSpace(ctx.String(flagDir))
  94. cache := ctx.Bool(flagCache)
  95. idea := ctx.Bool(flagIdea)
  96. style := ctx.String(flagStyle)
  97. schema := ctx.String(flagSchema)
  98. home := ctx.String(flagHome)
  99. remote := ctx.String(flagRemote)
  100. branch := ctx.String(flagBranch)
  101. if len(remote) > 0 {
  102. repo, _ := file.CloneIntoGitHome(remote, branch)
  103. if len(repo) > 0 {
  104. home = repo
  105. }
  106. }
  107. if len(home) > 0 {
  108. pathx.RegisterGoctlHome(home)
  109. }
  110. if len(schema) == 0 {
  111. schema = "public"
  112. }
  113. pattern := strings.TrimSpace(ctx.String(flagTable))
  114. cfg, err := config.NewConfig(style)
  115. if err != nil {
  116. return err
  117. }
  118. return fromPostgreSqlDataSource(url, pattern, dir, schema, cfg, cache, idea)
  119. }
  120. func fromDDL(src, dir string, cfg *config.Config, cache, idea bool, database string) error {
  121. log := console.NewConsole(idea)
  122. src = strings.TrimSpace(src)
  123. if len(src) == 0 {
  124. return errors.New("expected path or path globbing patterns, but nothing found")
  125. }
  126. files, err := util.MatchFiles(src)
  127. if err != nil {
  128. return err
  129. }
  130. if len(files) == 0 {
  131. return errNotMatched
  132. }
  133. generator, err := gen.NewDefaultGenerator(dir, cfg, gen.WithConsoleOption(log))
  134. if err != nil {
  135. return err
  136. }
  137. for _, file := range files {
  138. err = generator.StartFromDDL(file, cache, database)
  139. if err != nil {
  140. return err
  141. }
  142. }
  143. return nil
  144. }
  145. func fromMysqlDataSource(url, pattern, dir string, cfg *config.Config, cache, idea bool) error {
  146. log := console.NewConsole(idea)
  147. if len(url) == 0 {
  148. log.Error("%v", "expected data source of mysql, but nothing found")
  149. return nil
  150. }
  151. if len(pattern) == 0 {
  152. log.Error("%v", "expected table or table globbing patterns, but nothing found")
  153. return nil
  154. }
  155. dsn, err := mysql.ParseDSN(url)
  156. if err != nil {
  157. return err
  158. }
  159. logx.Disable()
  160. databaseSource := strings.TrimSuffix(url, "/"+dsn.DBName) + "/information_schema"
  161. db := sqlx.NewMysql(databaseSource)
  162. im := model.NewInformationSchemaModel(db)
  163. tables, err := im.GetAllTables(dsn.DBName)
  164. if err != nil {
  165. return err
  166. }
  167. matchTables := make(map[string]*model.Table)
  168. for _, item := range tables {
  169. match, err := filepath.Match(pattern, item)
  170. if err != nil {
  171. return err
  172. }
  173. if !match {
  174. continue
  175. }
  176. columnData, err := im.FindColumns(dsn.DBName, item)
  177. if err != nil {
  178. return err
  179. }
  180. table, err := columnData.Convert()
  181. if err != nil {
  182. return err
  183. }
  184. matchTables[item] = table
  185. }
  186. if len(matchTables) == 0 {
  187. return errors.New("no tables matched")
  188. }
  189. generator, err := gen.NewDefaultGenerator(dir, cfg, gen.WithConsoleOption(log))
  190. if err != nil {
  191. return err
  192. }
  193. return generator.StartFromInformationSchema(matchTables, cache)
  194. }
  195. func fromPostgreSqlDataSource(url, pattern, dir, schema string, cfg *config.Config, cache, idea bool) error {
  196. log := console.NewConsole(idea)
  197. if len(url) == 0 {
  198. log.Error("%v", "expected data source of postgresql, but nothing found")
  199. return nil
  200. }
  201. if len(pattern) == 0 {
  202. log.Error("%v", "expected table or table globbing patterns, but nothing found")
  203. return nil
  204. }
  205. db := postgres.New(url)
  206. im := model.NewPostgreSqlModel(db)
  207. tables, err := im.GetAllTables(schema)
  208. if err != nil {
  209. return err
  210. }
  211. matchTables := make(map[string]*model.Table)
  212. for _, item := range tables {
  213. match, err := filepath.Match(pattern, item)
  214. if err != nil {
  215. return err
  216. }
  217. if !match {
  218. continue
  219. }
  220. columnData, err := im.FindColumns(schema, item)
  221. if err != nil {
  222. return err
  223. }
  224. table, err := columnData.Convert()
  225. if err != nil {
  226. return err
  227. }
  228. matchTables[item] = table
  229. }
  230. if len(matchTables) == 0 {
  231. return errors.New("no tables matched")
  232. }
  233. generator, err := gen.NewDefaultGenerator(dir, cfg, gen.WithConsoleOption(log), gen.WithPostgreSql())
  234. if err != nil {
  235. return err
  236. }
  237. return generator.StartFromInformationSchema(matchTables, cache)
  238. }