feat: let model customizable (#1738)

master
Kevin Wan 3 years ago committed by GitHub
parent 7e0b0ab0b1
commit 6dccfa29fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -20,16 +20,13 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/util/stringx" "github.com/zeromicro/go-zero/tools/goctl/util/stringx"
) )
const ( const pwd = "."
pwd = "."
createTableFlag = `(?m)^(?i)CREATE\s+TABLE` // ignore case
)
type ( type (
defaultGenerator struct { defaultGenerator struct {
// source string
dir string
console.Console console.Console
// source string
dir string
pkg string pkg string
cfg *config.Config cfg *config.Config
isPostgreSql bool isPostgreSql bool
@ -48,6 +45,7 @@ type (
updateCode string updateCode string
deleteCode string deleteCode string
cacheExtra string cacheExtra string
tableName string
} }
codeTuple struct { codeTuple struct {
@ -154,7 +152,8 @@ func (g *defaultGenerator) createFile(modelList map[string]*codeTuple) error {
for tableName, codes := 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
} }
@ -202,7 +201,8 @@ func (g *defaultGenerator) createFile(modelList map[string]*codeTuple) 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]*codeTuple, error) { func (g *defaultGenerator) genFromDDL(filename string, withCache bool, database string) (
map[string]*codeTuple, error) {
m := make(map[string]*codeTuple) m := make(map[string]*codeTuple)
tables, err := parser.Parse(filename, database) tables, err := parser.Parse(filename, database)
if err != nil { if err != nil {
@ -249,7 +249,7 @@ func (g *defaultGenerator) genModel(in parser.Table, withCache bool) (string, er
table.UniqueCacheKey = uniqueKey table.UniqueCacheKey = uniqueKey
table.ContainsUniqueCacheKey = len(uniqueKey) > 0 table.ContainsUniqueCacheKey = len(uniqueKey) > 0
importsCode, err := genImports(withCache, in.ContainsTime(), table) importsCode, err := genImports(table, withCache, in.ContainsTime())
if err != nil { if err != nil {
return "", err return "", err
} }
@ -287,7 +287,8 @@ func (g *defaultGenerator) genModel(in parser.Table, withCache bool) (string, er
} }
var list []string var list []string
list = append(list, insertCodeMethod, findOneCodeMethod, ret.findOneInterfaceMethod, updateCodeMethod, deleteCodeMethod) list = append(list, insertCodeMethod, findOneCodeMethod, ret.findOneInterfaceMethod,
updateCodeMethod, deleteCodeMethod)
typesCode, err := genTypes(table, strings.Join(modelutil.TrimStringSlice(list), pathx.NL), withCache) typesCode, err := genTypes(table, strings.Join(modelutil.TrimStringSlice(list), pathx.NL), withCache)
if err != nil { if err != nil {
return "", err return "", err
@ -298,6 +299,11 @@ func (g *defaultGenerator) genModel(in parser.Table, withCache bool) (string, er
return "", err return "", err
} }
tableName, err := genTableName(table)
if err != nil {
return "", err
}
code := &code{ code := &code{
importsCode: importsCode, importsCode: importsCode,
varsCode: varsCode, varsCode: varsCode,
@ -308,6 +314,7 @@ func (g *defaultGenerator) genModel(in parser.Table, withCache bool) (string, er
updateCode: updateCode, updateCode: updateCode,
deleteCode: deleteCode, deleteCode: deleteCode,
cacheExtra: ret.cacheExtra, cacheExtra: ret.cacheExtra,
tableName: tableName,
} }
output, err := g.executeModel(table, code) output, err := g.executeModel(table, code)
@ -356,6 +363,7 @@ func (g *defaultGenerator) executeModel(table Table, code *code) (*bytes.Buffer,
"update": code.updateCode, "update": code.updateCode,
"delete": code.deleteCode, "delete": code.deleteCode,
"extraMethod": code.cacheExtra, "extraMethod": code.cacheExtra,
"tableName": code.tableName,
"data": table, "data": table,
}) })
if err != nil { if err != nil {

@ -6,7 +6,7 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
) )
func genImports(withCache, timeImport bool, table Table) (string, error) { func genImports(table Table, withCache, timeImport bool) (string, error) {
if withCache { if withCache {
text, err := pathx.LoadTemplate(category, importsTemplateFile, template.Imports) text, err := pathx.LoadTemplate(category, importsTemplateFile, template.Imports)
if err != nil { if err != nil {

@ -0,0 +1,26 @@
package gen
import (
"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/pathx"
)
func genTableName(table Table) (string, error) {
text, err := pathx.LoadTemplate(category, tableNameTemplateFile, template.TableName)
if err != nil {
return "", err
}
output, err := util.With("tableName").
Parse(text).
Execute(map[string]interface{}{
"tableName": table.Name.Source(),
"upperStartCamelObject": table.Name.ToCamel(),
})
if err != nil {
return "", nil
}
return output.String(), nil
}

@ -25,6 +25,7 @@ const (
modelGenTemplateFile = "model-gen.tpl" modelGenTemplateFile = "model-gen.tpl"
modelCustomTemplateFile = "model.tpl" modelCustomTemplateFile = "model.tpl"
modelNewTemplateFile = "model-new.tpl" modelNewTemplateFile = "model-new.tpl"
tableNameTemplateFile = "table-name.tpl"
tagTemplateFile = "tag.tpl" tagTemplateFile = "tag.tpl"
typesTemplateFile = "types.tpl" typesTemplateFile = "types.tpl"
updateTemplateFile = "update.tpl" updateTemplateFile = "update.tpl"
@ -49,6 +50,7 @@ var templates = map[string]string{
modelGenTemplateFile: template.ModelGen, modelGenTemplateFile: template.ModelGen,
modelCustomTemplateFile: template.ModelCustom, modelCustomTemplateFile: template.ModelCustom,
modelNewTemplateFile: template.New, modelNewTemplateFile: template.New,
tableNameTemplateFile: template.TableName,
tagTemplateFile: template.Tag, tagTemplateFile: template.Tag,
typesTemplateFile: template.Types, typesTemplateFile: template.Types,
updateTemplateFile: template.Update, updateTemplateFile: template.Update,
@ -72,7 +74,7 @@ func GenTemplates(_ *cli.Context) error {
return pathx.InitTemplates(category, templates) return pathx.InitTemplates(category, templates)
} }
// RevertTemplate recovers the delete template files // RevertTemplate reverts the deleted template files
func RevertTemplate(name string) error { func RevertTemplate(name string) error {
content, ok := templates[name] content, ok := templates[name]
if !ok { if !ok {

@ -1,7 +1,8 @@
package template package template
// Delete defines a delete template const (
var Delete = ` // Delete defines a delete template
Delete = `
func (m *default{{.upperStartCamelObject}}Model) Delete(ctx context.Context, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) error { func (m *default{{.upperStartCamelObject}}Model) Delete(ctx context.Context, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) error {
{{if .withCache}}{{if .containsIndexCache}}data, err:=m.FindOne(ctx, {{.lowerStartCamelPrimaryKey}}) {{if .withCache}}{{if .containsIndexCache}}data, err:=m.FindOne(ctx, {{.lowerStartCamelPrimaryKey}})
if err!=nil{ if err!=nil{
@ -18,5 +19,6 @@ func (m *default{{.upperStartCamelObject}}Model) Delete(ctx context.Context, {{.
} }
` `
// DeleteMethod defines a delete template for interface method // DeleteMethod defines a delete template for interface method
var DeleteMethod = `Delete(ctx context.Context, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) error` DeleteMethod = `Delete(ctx context.Context, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) error`
)

@ -1,7 +1,7 @@
package template package template
// Error defines an error template // Error defines an error template
var Error = `package {{.pkg}} const Error = `package {{.pkg}}
import "github.com/zeromicro/go-zero/core/stores/sqlx" import "github.com/zeromicro/go-zero/core/stores/sqlx"

@ -1,4 +1,4 @@
package template package template
// Field defines a filed template for types // Field defines a filed template for types
var Field = `{{.name}} {{.type}} {{.tag}} {{if .hasComment}}// {{.comment}}{{end}}` const Field = `{{.name}} {{.type}} {{.tag}} {{if .hasComment}}// {{.comment}}{{end}}`

@ -1,7 +1,8 @@
package template package template
// FindOne defines find row by id. const (
var FindOne = ` // FindOne defines find row by id.
FindOne = `
func (m *default{{.upperStartCamelObject}}Model) FindOne(ctx context.Context, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) (*{{.upperStartCamelObject}}, error) { func (m *default{{.upperStartCamelObject}}Model) FindOne(ctx context.Context, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) (*{{.upperStartCamelObject}}, error) {
{{if .withCache}}{{.cacheKey}} {{if .withCache}}{{.cacheKey}}
var resp {{.upperStartCamelObject}} var resp {{.upperStartCamelObject}}
@ -30,8 +31,8 @@ func (m *default{{.upperStartCamelObject}}Model) FindOne(ctx context.Context, {{
} }
` `
// FindOneByField defines find row by field. // FindOneByField defines find row by field.
var FindOneByField = ` FindOneByField = `
func (m *default{{.upperStartCamelObject}}Model) FindOneBy{{.upperField}}(ctx context.Context, {{.in}}) (*{{.upperStartCamelObject}}, error) { func (m *default{{.upperStartCamelObject}}Model) FindOneBy{{.upperField}}(ctx context.Context, {{.in}}) (*{{.upperStartCamelObject}}, error) {
{{if .withCache}}{{.cacheKey}} {{if .withCache}}{{.cacheKey}}
var resp {{.upperStartCamelObject}} var resp {{.upperStartCamelObject}}
@ -64,8 +65,8 @@ func (m *default{{.upperStartCamelObject}}Model) FindOneBy{{.upperField}}(ctx co
}{{end}} }{{end}}
` `
// FindOneByFieldExtraMethod defines find row by field with extras. // FindOneByFieldExtraMethod defines find row by field with extras.
var FindOneByFieldExtraMethod = ` FindOneByFieldExtraMethod = `
func (m *default{{.upperStartCamelObject}}Model) formatPrimary(primary interface{}) string { func (m *default{{.upperStartCamelObject}}Model) formatPrimary(primary interface{}) string {
return fmt.Sprintf("%s%v", {{.primaryKeyLeft}}, primary) return fmt.Sprintf("%s%v", {{.primaryKeyLeft}}, primary)
} }
@ -76,8 +77,9 @@ func (m *default{{.upperStartCamelObject}}Model) queryPrimary(ctx context.Contex
} }
` `
// FindOneMethod defines find row method. // FindOneMethod defines find row method.
var FindOneMethod = `FindOne(ctx context.Context, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) (*{{.upperStartCamelObject}}, error)` FindOneMethod = `FindOne(ctx context.Context, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) (*{{.upperStartCamelObject}}, error)`
// FindOneByFieldMethod defines find row by field method. // FindOneByFieldMethod defines find row by field method.
var FindOneByFieldMethod = `FindOneBy{{.upperField}}(ctx context.Context, {{.in}}) (*{{.upperStartCamelObject}}, error) ` FindOneByFieldMethod = `FindOneBy{{.upperField}}(ctx context.Context, {{.in}}) (*{{.upperStartCamelObject}}, error) `
)

@ -1,6 +1,6 @@
package template package template
var ( const (
// Imports defines a import template for model in cache case // Imports defines a import template for model in cache case
Imports = `import ( Imports = `import (
"context" "context"

@ -1,7 +1,8 @@
package template package template
// Insert defines a template for insert code in model const (
var Insert = ` // Insert defines a template for insert code in model
Insert = `
func (m *default{{.upperStartCamelObject}}Model) Insert(ctx context.Context, data *{{.upperStartCamelObject}}) (sql.Result,error) { func (m *default{{.upperStartCamelObject}}Model) Insert(ctx context.Context, data *{{.upperStartCamelObject}}) (sql.Result,error) {
{{if .withCache}}{{.keys}} {{if .withCache}}{{.keys}}
ret, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { ret, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
@ -13,5 +14,6 @@ func (m *default{{.upperStartCamelObject}}Model) Insert(ctx context.Context, dat
} }
` `
// InsertMethod defines an interface method template for insert code in model // InsertMethod defines an interface method template for insert code in model
var InsertMethod = `Insert(ctx context.Context, data *{{.upperStartCamelObject}}) (sql.Result,error)` InsertMethod = `Insert(ctx context.Context, data *{{.upperStartCamelObject}}) (sql.Result,error)`
)

@ -6,6 +6,33 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/util" "github.com/zeromicro/go-zero/tools/goctl/util"
) )
// ModelCustom defines a template for extension
const ModelCustom = `package {{.pkg}}
import "github.com/zeromicro/go-zero/core/stores/sqlx"
var _ {{.upperStartCamelObject}}Model = (*custom{{.upperStartCamelObject}}Model)(nil)
type (
// {{.upperStartCamelObject}}Model is an interface to be customized, add more methods here,
// and implement the added methods in custom{{.upperStartCamelObject}}Model.
{{.upperStartCamelObject}}Model interface {
{{.lowerStartCamelObject}}Model
}
custom{{.upperStartCamelObject}}Model struct {
*default{{.upperStartCamelObject}}Model
}
)
// New{{.upperStartCamelObject}}Model returns a model for the database table.
func New{{.upperStartCamelObject}}Model(conn sqlx.SqlConn{{if .withCache}}, c cache.CacheConf{{end}}) {{.upperStartCamelObject}}Model {
return &custom{{.upperStartCamelObject}}Model{
default{{.upperStartCamelObject}}Model: new{{.upperStartCamelObject}}Model(conn{{if .withCache}}, c{{end}}),
}
}
`
// ModelGen defines a template for model // ModelGen defines a template for model
var ModelGen = fmt.Sprintf(`%s var ModelGen = fmt.Sprintf(`%s
@ -19,11 +46,5 @@ package {{.pkg}}
{{.update}} {{.update}}
{{.delete}} {{.delete}}
{{.extraMethod}} {{.extraMethod}}
{{.tableName}}
`, util.DoNotEditHead) `, util.DoNotEditHead)
// ModelCustom defines a template for extension
var ModelCustom = fmt.Sprintf(`package {{.pkg}}
type {{.upperStartCamelObject}}Model interface {
{{.lowerStartCamelObject}}Model
}
`)

@ -1,8 +1,8 @@
package template package template
// New defines an template for creating model instance // New defines the template for creating model instance.
var New = ` const New = `
func New{{.upperStartCamelObject}}Model(conn sqlx.SqlConn{{if .withCache}}, c cache.CacheConf{{end}}) {{.upperStartCamelObject}}Model { func new{{.upperStartCamelObject}}Model(conn sqlx.SqlConn{{if .withCache}}, c cache.CacheConf{{end}}) *default{{.upperStartCamelObject}}Model {
return &default{{.upperStartCamelObject}}Model{ return &default{{.upperStartCamelObject}}Model{
{{if .withCache}}CachedConn: sqlc.NewConn(conn, c){{else}}conn:conn{{end}}, {{if .withCache}}CachedConn: sqlc.NewConn(conn, c){{else}}conn:conn{{end}},
table: {{.table}}, table: {{.table}},

@ -0,0 +1,8 @@
package template
// TableName defines a template that generate the tableName method.
const TableName = `
func (m *default{{.upperStartCamelObject}}Model) tableName() string {
return m.table
}
`

@ -1,4 +1,4 @@
package template package template
// Tag defines a tag template text // Tag defines a tag template text
var Tag = "`db:\"{{.field}}\"`" const Tag = "`db:\"{{.field}}\"`"

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

@ -1,7 +1,8 @@
package template package template
// Update defines a template for generating update codes const (
var Update = ` // Update defines a template for generating update codes
Update = `
func (m *default{{.upperStartCamelObject}}Model) Update(ctx context.Context, data *{{.upperStartCamelObject}}) error { func (m *default{{.upperStartCamelObject}}Model) Update(ctx context.Context, data *{{.upperStartCamelObject}}) error {
{{if .withCache}}{{.keys}} {{if .withCache}}{{.keys}}
_, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { _, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
@ -13,5 +14,6 @@ func (m *default{{.upperStartCamelObject}}Model) Update(ctx context.Context, dat
} }
` `
// UpdateMethod defines an interface method template for generating update codes // UpdateMethod defines an interface method template for generating update codes
var UpdateMethod = `Update(ctx context.Context, data *{{.upperStartCamelObject}}) error` UpdateMethod = `Update(ctx context.Context, data *{{.upperStartCamelObject}}) error`
)

@ -5,8 +5,6 @@ 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}}

Loading…
Cancel
Save