genmodel.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. package sqlmodel
  2. import (
  3. "bytes"
  4. "fmt"
  5. "go/ast"
  6. "go/parser"
  7. "go/token"
  8. "strings"
  9. "text/template"
  10. "zero/core/stringx"
  11. "zero/tools/goctl/api/spec"
  12. "zero/tools/goctl/util"
  13. )
  14. var (
  15. commonTemplate = `
  16. var (
  17. {{.modelWithLowerStart}}FieldNames = builderx.FieldNames(&{{.model}}{})
  18. {{.modelWithLowerStart}}Rows = strings.Join({{.modelWithLowerStart}}FieldNames, ",")
  19. {{.modelWithLowerStart}}RowsExpectAutoSet = strings.Join(stringx.Remove({{.modelWithLowerStart}}FieldNames, {{.expected}}), ",")
  20. {{.modelWithLowerStart}}RowsWithPlaceHolder = strings.Join(stringx.Remove({{.modelWithLowerStart}}FieldNames, {{.expected}}), "=?,") + "=?"
  21. )
  22. `
  23. )
  24. type (
  25. fieldExp struct {
  26. name string
  27. tag string
  28. ty string
  29. }
  30. structExp struct {
  31. genStruct GenStruct
  32. name string
  33. idAutoIncrement bool
  34. Fields []fieldExp
  35. primaryKey string
  36. conditions []string
  37. ignoreFields []string
  38. }
  39. )
  40. func NewStructExp(s GenStruct) (*structExp, error) {
  41. src := s.TableStruct
  42. fset := token.NewFileSet()
  43. file, err := parser.ParseFile(fset, "", src, 0)
  44. if err != nil {
  45. return nil, err
  46. }
  47. if len(file.Decls) == 0 {
  48. return nil, sqlError("no struct inspect")
  49. }
  50. typeDecl := file.Decls[0].(*ast.GenDecl)
  51. if len(typeDecl.Specs) == 0 {
  52. return nil, sqlError("no type specs")
  53. }
  54. typeSpec := typeDecl.Specs[0].(*ast.TypeSpec)
  55. structDecl := typeSpec.Type.(*ast.StructType)
  56. var strExp structExp
  57. strExp.genStruct = s
  58. strExp.primaryKey = s.PrimaryKey
  59. strExp.name = typeSpec.Name.Name
  60. fields := structDecl.Fields.List
  61. for _, field := range fields {
  62. typeExpr := field.Type
  63. start := typeExpr.Pos() - 1
  64. end := typeExpr.End() - 1
  65. typeInSource := src[start:end]
  66. if len(field.Names) == 0 {
  67. return nil, sqlError("field name empty")
  68. }
  69. var name = field.Names[0].Name
  70. var tag = util.Untitle(name)
  71. if field.Tag != nil {
  72. tag = src[field.Tag.Pos():field.Tag.End()]
  73. }
  74. dbTag := getDBColumnName(tag, name)
  75. strExp.Fields = append(strExp.Fields, fieldExp{
  76. name: name,
  77. ty: typeInSource,
  78. tag: dbTag,
  79. })
  80. if dbTag == strExp.primaryKey && typeInSource == "int64" {
  81. strExp.ignoreFields = append(strExp.ignoreFields, dbTag)
  82. strExp.idAutoIncrement = true
  83. }
  84. if name == "UpdateTime" || name == "CreateTime" {
  85. strExp.ignoreFields = append(strExp.ignoreFields, dbTag)
  86. }
  87. }
  88. return &strExp, nil
  89. }
  90. func (s *structExp) genMysqlCRUD() (string, error) {
  91. commonStr, err := s.genCommon()
  92. if err != nil {
  93. return "", err
  94. }
  95. insertStr, err := s.genInsert()
  96. if err != nil {
  97. return "", err
  98. }
  99. updateStr, err := s.genUpdate()
  100. if err != nil {
  101. return "", err
  102. }
  103. deleteStr, err := s.genDelete()
  104. if err != nil {
  105. return "", err
  106. }
  107. queryOneStr, err := s.genQueryOne()
  108. if err != nil {
  109. return "", err
  110. }
  111. queryListStr, err := s.genQueryList()
  112. if err != nil {
  113. return "", err
  114. }
  115. return strings.Join([]string{"package model \n", commonStr, s.genStruct.TableModel, queryOneStr, queryListStr, deleteStr, insertStr, updateStr}, "\n"), nil
  116. }
  117. func getDBColumnName(tag, name string) string {
  118. matches := spec.TagRe.FindStringSubmatch(tag)
  119. for i := range matches {
  120. name := spec.TagSubNames[i]
  121. if name == "name" {
  122. return matches[i]
  123. }
  124. }
  125. return util.Untitle(name)
  126. }
  127. func (s *structExp) genCommon() (string, error) {
  128. templateName := commonTemplate
  129. t := template.Must(template.New("commonTemplate").Parse(templateName))
  130. var tmplBytes bytes.Buffer
  131. var ignoreFieldsQuota []string
  132. for _, item := range s.ignoreFields {
  133. ignoreFieldsQuota = append(ignoreFieldsQuota, fmt.Sprintf("\"%s\"", item))
  134. }
  135. err := t.Execute(&tmplBytes, map[string]string{
  136. "model": s.name,
  137. "expected": strings.Join(ignoreFieldsQuota, ", "),
  138. "modelWithLowerStart": fmtUnderLine2Camel(s.name, false),
  139. })
  140. if err != nil {
  141. return "", err
  142. }
  143. return tmplBytes.String(), nil
  144. }
  145. func (s *structExp) buildCondition() (string, string) {
  146. var conditionExp []string
  147. var valueConditions []string
  148. for _, field := range s.Fields {
  149. if stringx.Contains(s.conditions, strings.ToLower(field.tag)) ||
  150. stringx.Contains(s.conditions, strings.ToLower(field.name)) {
  151. conditionExp = append(conditionExp, fmt.Sprintf("%s %s", util.Untitle(field.name), field.ty))
  152. valueConditions = append(valueConditions, fmt.Sprintf("%s = ?", field.tag))
  153. }
  154. }
  155. return strings.Join(conditionExp, ", "), strings.Join(valueConditions, " and ")
  156. }
  157. func (s *structExp) conditionNames() []string {
  158. var conditionExp []string
  159. for _, field := range s.Fields {
  160. if stringx.Contains(s.conditions, strings.ToLower(field.tag)) ||
  161. stringx.Contains(s.conditions, strings.ToLower(field.name)) {
  162. conditionExp = append(conditionExp, util.Untitle(field.name))
  163. }
  164. }
  165. return conditionExp
  166. }