command.go 6.0 KB

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