goctl added
This commit is contained in:
185
tools/goctl/model/sqlmodel/genmodel.go
Normal file
185
tools/goctl/model/sqlmodel/genmodel.go
Normal file
@@ -0,0 +1,185 @@
|
||||
package sqlmodel
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"zero/core/stringx"
|
||||
"zero/tools/goctl/api/spec"
|
||||
"zero/tools/goctl/util"
|
||||
)
|
||||
|
||||
var (
|
||||
commonTemplate = `
|
||||
var (
|
||||
{{.modelWithLowerStart}}FieldNames = builderx.FieldNames(&{{.model}}{})
|
||||
{{.modelWithLowerStart}}Rows = strings.Join({{.modelWithLowerStart}}FieldNames, ",")
|
||||
{{.modelWithLowerStart}}RowsExpectAutoSet = strings.Join(stringx.Remove({{.modelWithLowerStart}}FieldNames, {{.expected}}), ",")
|
||||
{{.modelWithLowerStart}}RowsWithPlaceHolder = strings.Join(stringx.Remove({{.modelWithLowerStart}}FieldNames, {{.expected}}), "=?,") + "=?"
|
||||
)
|
||||
`
|
||||
)
|
||||
|
||||
type (
|
||||
fieldExp struct {
|
||||
name string
|
||||
tag string
|
||||
ty string
|
||||
}
|
||||
structExp struct {
|
||||
genStruct GenStruct
|
||||
name string
|
||||
idAutoIncrement bool
|
||||
Fields []fieldExp
|
||||
primaryKey string
|
||||
conditions []string
|
||||
ignoreFields []string
|
||||
}
|
||||
)
|
||||
|
||||
func NewStructExp(s GenStruct) (*structExp, error) {
|
||||
src := s.TableStruct
|
||||
fset := token.NewFileSet()
|
||||
file, err := parser.ParseFile(fset, "", src, 0)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(file.Decls) == 0 {
|
||||
return nil, sqlError("no struct inspect")
|
||||
}
|
||||
typeDecl := file.Decls[0].(*ast.GenDecl)
|
||||
|
||||
if len(typeDecl.Specs) == 0 {
|
||||
return nil, sqlError("no type specs")
|
||||
}
|
||||
typeSpec := typeDecl.Specs[0].(*ast.TypeSpec)
|
||||
structDecl := typeSpec.Type.(*ast.StructType)
|
||||
|
||||
var strExp structExp
|
||||
strExp.genStruct = s
|
||||
strExp.primaryKey = s.PrimaryKey
|
||||
strExp.name = typeSpec.Name.Name
|
||||
fields := structDecl.Fields.List
|
||||
for _, field := range fields {
|
||||
typeExpr := field.Type
|
||||
|
||||
start := typeExpr.Pos() - 1
|
||||
end := typeExpr.End() - 1
|
||||
|
||||
typeInSource := src[start:end]
|
||||
if len(field.Names) == 0 {
|
||||
return nil, sqlError("field name empty")
|
||||
}
|
||||
var name = field.Names[0].Name
|
||||
var tag = util.Untitle(name)
|
||||
if field.Tag != nil {
|
||||
tag = src[field.Tag.Pos():field.Tag.End()]
|
||||
}
|
||||
dbTag := getDBColumnName(tag, name)
|
||||
strExp.Fields = append(strExp.Fields, fieldExp{
|
||||
name: name,
|
||||
ty: typeInSource,
|
||||
tag: dbTag,
|
||||
})
|
||||
if dbTag == strExp.primaryKey && typeInSource == "int64" {
|
||||
strExp.ignoreFields = append(strExp.ignoreFields, dbTag)
|
||||
strExp.idAutoIncrement = true
|
||||
}
|
||||
if name == "UpdateTime" || name == "CreateTime" {
|
||||
strExp.ignoreFields = append(strExp.ignoreFields, dbTag)
|
||||
}
|
||||
}
|
||||
return &strExp, nil
|
||||
}
|
||||
|
||||
func (s *structExp) genMysqlCRUD() (string, error) {
|
||||
commonStr, err := s.genCommon()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
insertStr, err := s.genInsert()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
updateStr, err := s.genUpdate()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
deleteStr, err := s.genDelete()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
queryOneStr, err := s.genQueryOne()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
queryListStr, err := s.genQueryList()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strings.Join([]string{"package model \n", commonStr, s.genStruct.TableModel, queryOneStr, queryListStr, deleteStr, insertStr, updateStr}, "\n"), nil
|
||||
}
|
||||
|
||||
func getDBColumnName(tag, name string) string {
|
||||
matches := spec.TagRe.FindStringSubmatch(tag)
|
||||
for i := range matches {
|
||||
name := spec.TagSubNames[i]
|
||||
if name == "name" {
|
||||
return matches[i]
|
||||
}
|
||||
}
|
||||
|
||||
return util.Untitle(name)
|
||||
}
|
||||
|
||||
func (s *structExp) genCommon() (string, error) {
|
||||
templateName := commonTemplate
|
||||
t := template.Must(template.New("commonTemplate").Parse(templateName))
|
||||
var tmplBytes bytes.Buffer
|
||||
var ignoreFieldsQuota []string
|
||||
for _, item := range s.ignoreFields {
|
||||
ignoreFieldsQuota = append(ignoreFieldsQuota, fmt.Sprintf("\"%s\"", item))
|
||||
}
|
||||
err := t.Execute(&tmplBytes, map[string]string{
|
||||
"model": s.name,
|
||||
"expected": strings.Join(ignoreFieldsQuota, ", "),
|
||||
"modelWithLowerStart": fmtUnderLine2Camel(s.name, false),
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return tmplBytes.String(), nil
|
||||
}
|
||||
|
||||
func (s *structExp) buildCondition() (string, string) {
|
||||
var conditionExp []string
|
||||
var valueConditions []string
|
||||
for _, field := range s.Fields {
|
||||
if stringx.Contains(s.conditions, strings.ToLower(field.tag)) ||
|
||||
stringx.Contains(s.conditions, strings.ToLower(field.name)) {
|
||||
conditionExp = append(conditionExp, fmt.Sprintf("%s %s", util.Untitle(field.name), field.ty))
|
||||
valueConditions = append(valueConditions, fmt.Sprintf("%s = ?", field.tag))
|
||||
}
|
||||
}
|
||||
return strings.Join(conditionExp, ", "), strings.Join(valueConditions, " and ")
|
||||
}
|
||||
|
||||
func (s *structExp) conditionNames() []string {
|
||||
var conditionExp []string
|
||||
for _, field := range s.Fields {
|
||||
if stringx.Contains(s.conditions, strings.ToLower(field.tag)) ||
|
||||
stringx.Contains(s.conditions, strings.ToLower(field.name)) {
|
||||
conditionExp = append(conditionExp, util.Untitle(field.name))
|
||||
}
|
||||
}
|
||||
return conditionExp
|
||||
}
|
||||
Reference in New Issue
Block a user