feat(goctl): supports model code 'DO NOT EDIT' (#1728)

Resolves: #1710
master
Fyn 3 years ago committed by GitHub
parent 9c2d526a11
commit f4471846ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -49,6 +49,11 @@ type (
deleteCode string deleteCode string
cacheExtra string cacheExtra string
} }
codeTuple struct {
modelCode string
modelCustomCode string
}
) )
// NewDefaultGenerator creates an instance for defaultGenerator // NewDefaultGenerator creates an instance for defaultGenerator
@ -109,7 +114,7 @@ func (g *defaultGenerator) StartFromDDL(filename string, withCache bool, databas
} }
func (g *defaultGenerator) StartFromInformationSchema(tables map[string]*model.Table, withCache bool) error { func (g *defaultGenerator) StartFromInformationSchema(tables map[string]*model.Table, withCache bool) error {
m := make(map[string]string) m := make(map[string]*codeTuple)
for _, each := range tables { for _, each := range tables {
table, err := parser.ConvertDataType(each) table, err := parser.ConvertDataType(each)
if err != nil { if err != nil {
@ -120,14 +125,21 @@ func (g *defaultGenerator) StartFromInformationSchema(tables map[string]*model.T
if err != nil { if err != nil {
return err return err
} }
customCode, err := g.genModelCustom(*table)
if err != nil {
return err
}
m[table.Name.Source()] = code m[table.Name.Source()] = &codeTuple{
modelCode: code,
modelCustomCode: customCode,
}
} }
return g.createFile(m) return g.createFile(m)
} }
func (g *defaultGenerator) createFile(modelList map[string]string) error { func (g *defaultGenerator) createFile(modelList map[string]*codeTuple) error {
dirAbs, err := filepath.Abs(g.dir) dirAbs, err := filepath.Abs(g.dir)
if err != nil { if err != nil {
return err return err
@ -140,20 +152,27 @@ func (g *defaultGenerator) createFile(modelList map[string]string) error {
return err return err
} }
for tableName, code := range modelList { for tableName, codes := range modelList {
tn := stringx.From(tableName) tn := stringx.From(tableName)
modelFilename, err := format.FileNamingFormat(g.cfg.NamingFormat, fmt.Sprintf("%s_model", tn.Source())) modelFilename, err := format.FileNamingFormat(g.cfg.NamingFormat, fmt.Sprintf("%s_model", tn.Source()))
if err != nil { if err != nil {
return err return err
} }
name := util.SafeString(modelFilename) + ".go" name := util.SafeString(modelFilename) + "_gen.go"
filename := filepath.Join(dirAbs, name) filename := filepath.Join(dirAbs, name)
err = ioutil.WriteFile(filename, []byte(codes.modelCode), os.ModePerm)
if err != nil {
return err
}
name = util.SafeString(modelFilename) + ".go"
filename = filepath.Join(dirAbs, name)
if pathx.FileExists(filename) { if pathx.FileExists(filename) {
g.Warning("%s already exists, ignored.", name) g.Warning("%s already exists, ignored.", name)
continue continue
} }
err = ioutil.WriteFile(filename, []byte(code), os.ModePerm) err = ioutil.WriteFile(filename, []byte(codes.modelCustomCode), os.ModePerm)
if err != nil { if err != nil {
return err return err
} }
@ -183,8 +202,8 @@ func (g *defaultGenerator) createFile(modelList map[string]string) error {
} }
// ret1: key-table name,value-code // ret1: key-table name,value-code
func (g *defaultGenerator) genFromDDL(filename string, withCache bool, database string) (map[string]string, error) { func (g *defaultGenerator) genFromDDL(filename string, withCache bool, database string) (map[string]*codeTuple, error) {
m := make(map[string]string) m := make(map[string]*codeTuple)
tables, err := parser.Parse(filename, database) tables, err := parser.Parse(filename, database)
if err != nil { if err != nil {
return nil, err return nil, err
@ -195,8 +214,15 @@ func (g *defaultGenerator) genFromDDL(filename string, withCache bool, database
if err != nil { if err != nil {
return nil, err return nil, err
} }
customCode, err := g.genModelCustom(*e)
if err != nil {
return nil, err
}
m[e.Name.Source()] = code m[e.Name.Source()] = &codeTuple{
modelCode: code,
modelCustomCode: customCode,
}
} }
return m, nil return m, nil
@ -292,8 +318,27 @@ func (g *defaultGenerator) genModel(in parser.Table, withCache bool) (string, er
return output.String(), nil return output.String(), nil
} }
func (g *defaultGenerator) genModelCustom(in parser.Table) (string, error) {
text, err := pathx.LoadTemplate(category, modelCustomTemplateFile, template.ModelCustom)
if err != nil {
return "", err
}
t := util.With("model-custom").
Parse(text).
GoFmt(true)
output, err := t.Execute(map[string]interface{}{
"pkg": g.pkg,
"upperStartCamelObject": in.Name.ToCamel(),
"lowerStartCamelObject": stringx.From(in.Name.ToCamel()).Untitle(),
})
if err != nil {
return "", err
}
return output.String(), nil
}
func (g *defaultGenerator) executeModel(table Table, code *code) (*bytes.Buffer, error) { func (g *defaultGenerator) executeModel(table Table, code *code) (*bytes.Buffer, error) {
text, err := pathx.LoadTemplate(category, modelTemplateFile, template.Model) text, err := pathx.LoadTemplate(category, modelGenTemplateFile, template.ModelGen)
if err != nil { if err != nil {
return nil, err return nil, err
} }

@ -4,16 +4,19 @@ import (
"database/sql" "database/sql"
"io/ioutil" "io/ioutil"
"os" "os"
"path"
"path/filepath" "path/filepath"
"strings" "strings"
"testing" "testing"
"time" "time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stringx" "github.com/zeromicro/go-zero/core/stringx"
"github.com/zeromicro/go-zero/tools/goctl/config" "github.com/zeromicro/go-zero/tools/goctl/config"
"github.com/zeromicro/go-zero/tools/goctl/model/sql/builderx" "github.com/zeromicro/go-zero/tools/goctl/model/sql/builderx"
"github.com/zeromicro/go-zero/tools/goctl/model/sql/parser"
"github.com/zeromicro/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
) )
@ -121,3 +124,28 @@ func TestFields(t *testing.T) {
assert.Equal(t, "`name`,`age`,`score`", studentRowsExpectAutoSet) assert.Equal(t, "`name`,`age`,`score`", studentRowsExpectAutoSet)
assert.Equal(t, "`name`=?,`age`=?,`score`=?", studentRowsWithPlaceHolder) assert.Equal(t, "`name`=?,`age`=?,`score`=?", studentRowsWithPlaceHolder)
} }
func Test_genPublicModel(t *testing.T) {
var err error
dir := pathx.MustTempDir()
modelDir := path.Join(dir, "model")
err = os.MkdirAll(modelDir, 0777)
require.NoError(t, err)
defer os.RemoveAll(dir)
modelFilename := filepath.Join(modelDir, "foo.sql")
err = ioutil.WriteFile(modelFilename, []byte(source), 0777)
require.NoError(t, err)
g, err := NewDefaultGenerator(modelDir, &config.Config{
NamingFormat: config.DefaultFormat,
})
require.NoError(t, err)
tables, err := parser.Parse(modelFilename, "")
require.Equal(t, 1, len(tables))
code, err := g.genModelCustom(*tables[0])
assert.NoError(t, err)
assert.Equal(t, "package model\n\ntype TestUserModel interface {\n\ttestUserModel\n}\n", code)
}

@ -22,7 +22,8 @@ const (
importsWithNoCacheTemplateFile = "import-no-cache.tpl" importsWithNoCacheTemplateFile = "import-no-cache.tpl"
insertTemplateFile = "insert.tpl" insertTemplateFile = "insert.tpl"
insertTemplateMethodFile = "interface-insert.tpl" insertTemplateMethodFile = "interface-insert.tpl"
modelTemplateFile = "model.tpl" modelGenTemplateFile = "model-gen.tpl"
modelCustomTemplateFile = "model.tpl"
modelNewTemplateFile = "model-new.tpl" modelNewTemplateFile = "model-new.tpl"
tagTemplateFile = "tag.tpl" tagTemplateFile = "tag.tpl"
typesTemplateFile = "types.tpl" typesTemplateFile = "types.tpl"
@ -45,7 +46,8 @@ var templates = map[string]string{
importsWithNoCacheTemplateFile: template.ImportsNoCache, importsWithNoCacheTemplateFile: template.ImportsNoCache,
insertTemplateFile: template.Insert, insertTemplateFile: template.Insert,
insertTemplateMethodFile: template.InsertMethod, insertTemplateMethodFile: template.InsertMethod,
modelTemplateFile: template.Model, modelGenTemplateFile: template.ModelGen,
modelCustomTemplateFile: template.ModelCustom,
modelNewTemplateFile: template.New, modelNewTemplateFile: template.New,
tagTemplateFile: template.Tag, tagTemplateFile: template.Tag,
typesTemplateFile: template.Types, typesTemplateFile: template.Types,

@ -4,6 +4,7 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/model/sql/template" "github.com/zeromicro/go-zero/tools/goctl/model/sql/template"
"github.com/zeromicro/go-zero/tools/goctl/util" "github.com/zeromicro/go-zero/tools/goctl/util"
"github.com/zeromicro/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
"github.com/zeromicro/go-zero/tools/goctl/util/stringx"
) )
func genTypes(table Table, methods string, withCache bool) (string, error) { func genTypes(table Table, methods string, withCache bool) (string, error) {
@ -24,6 +25,7 @@ func genTypes(table Table, methods string, withCache bool) (string, error) {
"withCache": withCache, "withCache": withCache,
"method": methods, "method": methods,
"upperStartCamelObject": table.Name.ToCamel(), "upperStartCamelObject": table.Name.ToCamel(),
"lowerStartCamelObject": stringx.From(table.Name.ToCamel()).Untitle(),
"fields": fieldsString, "fields": fieldsString,
"data": table, "data": table,
}) })

@ -1,7 +1,15 @@
package template package template
// Model defines a template for model import (
var Model = `package {{.pkg}} "fmt"
"github.com/zeromicro/go-zero/tools/goctl/util"
)
// ModelGen defines a template for model
var ModelGen = fmt.Sprintf(`%s
package {{.pkg}}
{{.imports}} {{.imports}}
{{.vars}} {{.vars}}
{{.types}} {{.types}}
@ -11,4 +19,11 @@ var Model = `package {{.pkg}}
{{.update}} {{.update}}
{{.delete}} {{.delete}}
{{.extraMethod}} {{.extraMethod}}
` `, util.DoNotEditHead)
// ModelCustom defines a template for extension
var ModelCustom = fmt.Sprintf(`package {{.pkg}}
type {{.upperStartCamelObject}}Model interface {
{{.lowerStartCamelObject}}Model
}
`)

@ -3,7 +3,7 @@ package template
// Types defines a template for types in model // Types defines a template for types in model
var Types = ` var Types = `
type ( type (
{{.upperStartCamelObject}}Model interface{ {{.lowerStartCamelObject}}Model interface{
{{.method}} {{.method}}
} }

@ -5,6 +5,8 @@ import "fmt"
// Vars defines a template for var block in model // Vars defines a template for var block in model
var Vars = fmt.Sprintf(` var Vars = fmt.Sprintf(`
var ( var (
_ {{.upperStartCamelObject}}Model = (*default{{.upperStartCamelObject}}Model)(nil)
{{.lowerStartCamelObject}}FieldNames = builder.RawFieldNames(&{{.upperStartCamelObject}}{}{{if .postgreSql}},true{{end}}) {{.lowerStartCamelObject}}FieldNames = builder.RawFieldNames(&{{.upperStartCamelObject}}{}{{if .postgreSql}},true{{end}})
{{.lowerStartCamelObject}}Rows = strings.Join({{.lowerStartCamelObject}}FieldNames, ",") {{.lowerStartCamelObject}}Rows = strings.Join({{.lowerStartCamelObject}}FieldNames, ",")
{{.lowerStartCamelObject}}RowsExpectAutoSet = {{if .postgreSql}}strings.Join(stringx.Remove({{.lowerStartCamelObject}}FieldNames, {{if .autoIncrement}}"{{.originalPrimaryKey}}",{{end}} "%screate_time%s", "%supdate_time%s"), ","){{else}}strings.Join(stringx.Remove({{.lowerStartCamelObject}}FieldNames, {{if .autoIncrement}}"{{.originalPrimaryKey}}",{{end}} "%screate_time%s", "%supdate_time%s"), ","){{end}} {{.lowerStartCamelObject}}RowsExpectAutoSet = {{if .postgreSql}}strings.Join(stringx.Remove({{.lowerStartCamelObject}}FieldNames, {{if .autoIncrement}}"{{.originalPrimaryKey}}",{{end}} "%screate_time%s", "%supdate_time%s"), ","){{else}}strings.Join(stringx.Remove({{.lowerStartCamelObject}}FieldNames, {{if .autoIncrement}}"{{.originalPrimaryKey}}",{{end}} "%screate_time%s", "%supdate_time%s"), ","){{end}}

@ -1,5 +1,8 @@
package util package util
// DoNotEditHead added to the beginning of a file to prompt the user not to edit
var DoNotEditHead = "// Code generated by goctl. DO NOT EDIT!"
var headTemplate = `// Code generated by goctl. DO NOT EDIT! var headTemplate = `// Code generated by goctl. DO NOT EDIT!
// Source: {{.source}}` // Source: {{.source}}`

Loading…
Cancel
Save