gendao_dao.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. // Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
  2. //
  3. // This Source Code Form is subject to the terms of the MIT License.
  4. // If a copy of the MIT was not distributed with this file,
  5. // You can obtain one at https://github.com/gogf/gf.
  6. package gendao
  7. import (
  8. "bytes"
  9. "context"
  10. "fmt"
  11. "strings"
  12. "github.com/olekukonko/tablewriter"
  13. "github.com/gogf/gf/v2/database/gdb"
  14. "github.com/gogf/gf/v2/frame/g"
  15. "github.com/gogf/gf/v2/os/gfile"
  16. "github.com/gogf/gf/v2/text/gstr"
  17. "github.com/gogf/gf/cmd/gf/v2/internal/consts"
  18. "github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
  19. "github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
  20. )
  21. func generateDao(ctx context.Context, in CGenDaoInternalInput) {
  22. var (
  23. dirPathDao = gfile.Join(in.Path, in.DaoPath)
  24. dirPathDaoInternal = gfile.Join(dirPathDao, "internal")
  25. )
  26. if in.Clear {
  27. doClear(ctx, dirPathDao, true)
  28. }
  29. for i := 0; i < len(in.TableNames); i++ {
  30. generateDaoSingle(ctx, generateDaoSingleInput{
  31. CGenDaoInternalInput: in,
  32. TableName: in.TableNames[i],
  33. NewTableName: in.NewTableNames[i],
  34. DirPathDao: dirPathDao,
  35. DirPathDaoInternal: dirPathDaoInternal,
  36. })
  37. }
  38. }
  39. type generateDaoSingleInput struct {
  40. CGenDaoInternalInput
  41. TableName string // TableName specifies the table name of the table.
  42. NewTableName string // NewTableName specifies the prefix-stripped name of the table.
  43. DirPathDao string
  44. DirPathDaoInternal string
  45. }
  46. // generateDaoSingle generates the dao and model content of given table.
  47. func generateDaoSingle(ctx context.Context, in generateDaoSingleInput) {
  48. // Generating table data preparing.
  49. fieldMap, err := in.DB.TableFields(ctx, in.TableName)
  50. if err != nil {
  51. mlog.Fatalf(`fetching tables fields failed for table "%s": %+v`, in.TableName, err)
  52. }
  53. var (
  54. tableNameCamelCase = gstr.CaseCamel(in.NewTableName)
  55. tableNameCamelLowerCase = gstr.CaseCamelLower(in.NewTableName)
  56. tableNameSnakeCase = gstr.CaseSnake(in.NewTableName)
  57. importPrefix = in.ImportPrefix
  58. )
  59. if importPrefix == "" {
  60. importPrefix = utils.GetImportPath(gfile.Join(in.Path, in.DaoPath))
  61. } else {
  62. importPrefix = gstr.Join(g.SliceStr{importPrefix, in.DaoPath}, "/")
  63. }
  64. fileName := gstr.Trim(tableNameSnakeCase, "-_.")
  65. if len(fileName) > 5 && fileName[len(fileName)-5:] == "_test" {
  66. // Add suffix to avoid the table name which contains "_test",
  67. // which would make the go file a testing file.
  68. fileName += "_table"
  69. }
  70. // dao - index
  71. generateDaoIndex(generateDaoIndexInput{
  72. generateDaoSingleInput: in,
  73. TableNameCamelCase: tableNameCamelCase,
  74. TableNameCamelLowerCase: tableNameCamelLowerCase,
  75. ImportPrefix: importPrefix,
  76. FileName: fileName,
  77. })
  78. // dao - internal
  79. generateDaoInternal(generateDaoInternalInput{
  80. generateDaoSingleInput: in,
  81. TableNameCamelCase: tableNameCamelCase,
  82. TableNameCamelLowerCase: tableNameCamelLowerCase,
  83. ImportPrefix: importPrefix,
  84. FileName: fileName,
  85. FieldMap: fieldMap,
  86. })
  87. }
  88. type generateDaoIndexInput struct {
  89. generateDaoSingleInput
  90. TableNameCamelCase string
  91. TableNameCamelLowerCase string
  92. ImportPrefix string
  93. FileName string
  94. }
  95. func generateDaoIndex(in generateDaoIndexInput) {
  96. path := gfile.Join(in.DirPathDao, in.FileName+".go")
  97. if in.OverwriteDao || !gfile.Exists(path) {
  98. indexContent := gstr.ReplaceByMap(
  99. getTemplateFromPathOrDefault(in.TplDaoIndexPath, consts.TemplateGenDaoIndexContent),
  100. g.MapStrStr{
  101. tplVarImportPrefix: in.ImportPrefix,
  102. tplVarTableName: in.TableName,
  103. tplVarTableNameCamelCase: in.TableNameCamelCase,
  104. tplVarTableNameCamelLowerCase: in.TableNameCamelLowerCase,
  105. })
  106. indexContent = replaceDefaultVar(in.CGenDaoInternalInput, indexContent)
  107. if err := gfile.PutContents(path, strings.TrimSpace(indexContent)); err != nil {
  108. mlog.Fatalf("writing content to '%s' failed: %v", path, err)
  109. } else {
  110. utils.GoFmt(path)
  111. mlog.Print("generated:", path)
  112. }
  113. }
  114. }
  115. type generateDaoInternalInput struct {
  116. generateDaoSingleInput
  117. TableNameCamelCase string
  118. TableNameCamelLowerCase string
  119. ImportPrefix string
  120. FileName string
  121. FieldMap map[string]*gdb.TableField
  122. }
  123. func generateDaoInternal(in generateDaoInternalInput) {
  124. path := gfile.Join(in.DirPathDaoInternal, in.FileName+".go")
  125. modelContent := gstr.ReplaceByMap(
  126. getTemplateFromPathOrDefault(in.TplDaoInternalPath, consts.TemplateGenDaoInternalContent),
  127. g.MapStrStr{
  128. tplVarImportPrefix: in.ImportPrefix,
  129. tplVarTableName: in.TableName,
  130. tplVarGroupName: in.Group,
  131. tplVarTableNameCamelCase: in.TableNameCamelCase,
  132. tplVarTableNameCamelLowerCase: in.TableNameCamelLowerCase,
  133. tplVarColumnDefine: gstr.Trim(generateColumnDefinitionForDao(in.FieldMap)),
  134. tplVarColumnNames: gstr.Trim(generateColumnNamesForDao(in.FieldMap)),
  135. })
  136. modelContent = replaceDefaultVar(in.CGenDaoInternalInput, modelContent)
  137. if err := gfile.PutContents(path, strings.TrimSpace(modelContent)); err != nil {
  138. mlog.Fatalf("writing content to '%s' failed: %v", path, err)
  139. } else {
  140. utils.GoFmt(path)
  141. mlog.Print("generated:", path)
  142. }
  143. }
  144. // generateColumnNamesForDao generates and returns the column names assignment content of column struct
  145. // for specified table.
  146. func generateColumnNamesForDao(fieldMap map[string]*gdb.TableField) string {
  147. var (
  148. buffer = bytes.NewBuffer(nil)
  149. array = make([][]string, len(fieldMap))
  150. names = sortFieldKeyForDao(fieldMap)
  151. )
  152. for index, name := range names {
  153. field := fieldMap[name]
  154. array[index] = []string{
  155. " #" + gstr.CaseCamel(field.Name) + ":",
  156. fmt.Sprintf(` #"%s",`, field.Name),
  157. }
  158. }
  159. tw := tablewriter.NewWriter(buffer)
  160. tw.SetBorder(false)
  161. tw.SetRowLine(false)
  162. tw.SetAutoWrapText(false)
  163. tw.SetColumnSeparator("")
  164. tw.AppendBulk(array)
  165. tw.Render()
  166. namesContent := buffer.String()
  167. // Let's do this hack of table writer for indent!
  168. namesContent = gstr.Replace(namesContent, " #", "")
  169. buffer.Reset()
  170. buffer.WriteString(namesContent)
  171. return buffer.String()
  172. }
  173. // generateColumnDefinitionForDao generates and returns the column names definition for specified table.
  174. func generateColumnDefinitionForDao(fieldMap map[string]*gdb.TableField) string {
  175. var (
  176. buffer = bytes.NewBuffer(nil)
  177. array = make([][]string, len(fieldMap))
  178. names = sortFieldKeyForDao(fieldMap)
  179. )
  180. for index, name := range names {
  181. var (
  182. field = fieldMap[name]
  183. comment = gstr.Trim(gstr.ReplaceByArray(field.Comment, g.SliceStr{
  184. "\n", " ",
  185. "\r", " ",
  186. }))
  187. )
  188. array[index] = []string{
  189. " #" + gstr.CaseCamel(field.Name),
  190. " # " + "string",
  191. " #" + fmt.Sprintf(`// %s`, comment),
  192. }
  193. }
  194. tw := tablewriter.NewWriter(buffer)
  195. tw.SetBorder(false)
  196. tw.SetRowLine(false)
  197. tw.SetAutoWrapText(false)
  198. tw.SetColumnSeparator("")
  199. tw.AppendBulk(array)
  200. tw.Render()
  201. defineContent := buffer.String()
  202. // Let's do this hack of table writer for indent!
  203. defineContent = gstr.Replace(defineContent, " #", "")
  204. buffer.Reset()
  205. buffer.WriteString(defineContent)
  206. return buffer.String()
  207. }