feature model interface (#222)

* make variable declaration more concise

* add model interface

* optimize interface methods

* fix: go test failed

* warp returns

* optimize
master
Keson 4 years ago committed by GitHub
parent b9ac51b6c3
commit 6e57f6c527
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -7,7 +7,7 @@ goctl model 为go-zero下的工具模块中的组件之一目前支持识别m
* 通过ddl生成 * 通过ddl生成
```shell script ```shell script
goctl model mysql ddl -src="./*.sql" -dir="./sql/model" -c=true goctl model mysql ddl -src="./*.sql" -dir="./sql/model" -c
``` ```
执行上述命令后即可快速生成CURD代码。 执行上述命令后即可快速生成CURD代码。
@ -29,156 +29,191 @@ goctl model 为go-zero下的工具模块中的组件之一目前支持识别m
```go ```go
package model package model
import (
"database/sql"
"fmt"
"strings"
"time"
"github.com/tal-tech/go-zero/core/stores/cache"
"github.com/tal-tech/go-zero/core/stores/sqlc"
"github.com/tal-tech/go-zero/core/stores/sqlx"
"github.com/tal-tech/go-zero/core/stringx"
"github.com/tal-tech/go-zero/tools/goctl/model/sql/builderx"
)
var (
userFieldNames = builderx.FieldNames(&User{})
userRows = strings.Join(userFieldNames, ",")
userRowsExpectAutoSet = strings.Join(stringx.Remove(userFieldNames, "id", "create_time", "update_time"), ",")
userRowsWithPlaceHolder = strings.Join(stringx.Remove(userFieldNames, "id", "create_time", "update_time"), "=?,") + "=?"
cacheUserPrefix = "cache#User#user#"
cacheUserNamePrefix = "cache#User#name#"
cacheUserMobilePrefix = "cache#User#mobile#"
cacheUserIdPrefix = "cache#User#id#"
)
type (
UserModel interface {
Insert(data User) (sql.Result, error)
FindOne(id int64) (*User, error)
FindOneByUser(user string) (*User, error)
FindOneByName(name string) (*User, error)
FindOneByMobile(mobile string) (*User, error)
Update(data User) error
Delete(id int64) error
}
defaultUserModel struct {
sqlc.CachedConn
table string
}
User struct {
Id int64 `db:"id"`
User string `db:"user"` // 用户
Name string `db:"name"` // 用户名称
Password string `db:"password"` // 用户密码
Mobile string `db:"mobile"` // 手机号
Gender string `db:"gender"` // 男|女|未公开
Nickname string `db:"nickname"` // 用户昵称
CreateTime time.Time `db:"create_time"`
UpdateTime time.Time `db:"update_time"`
}
)
func NewUserModel(conn sqlx.SqlConn, c cache.CacheConf) UserModel {
return &defaultUserModel{
CachedConn: sqlc.NewConn(conn, c),
table: "user",
}
}
func (m *defaultUserModel) Insert(data User) (sql.Result, error) {
userKey := fmt.Sprintf("%s%v", cacheUserPrefix, data.User)
userNameKey := fmt.Sprintf("%s%v", cacheUserNamePrefix, data.Name)
userMobileKey := fmt.Sprintf("%s%v", cacheUserMobilePrefix, data.Mobile)
ret, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?)", m.table, userRowsExpectAutoSet)
return conn.Exec(query, data.User, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname)
}, userMobileKey, userKey, userNameKey)
return ret, err
}
func (m *defaultUserModel) FindOne(id int64) (*User, error) {
userIdKey := fmt.Sprintf("%s%v", cacheUserIdPrefix, id)
var resp User
err := m.QueryRow(&resp, userIdKey, func(conn sqlx.SqlConn, v interface{}) error {
query := fmt.Sprintf("select %s from %s where id = ? limit 1", userRows, m.table)
return conn.QueryRow(v, query, id)
})
switch err {
case nil:
return &resp, nil
case sqlc.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultUserModel) FindOneByUser(user string) (*User, error) {
userKey := fmt.Sprintf("%s%v", cacheUserPrefix, user)
var resp User
err := m.QueryRowIndex(&resp, userKey, m.formatPrimary, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
query := fmt.Sprintf("select %s from %s where user = ? limit 1", userRows, m.table)
if err := conn.QueryRow(&resp, query, user); err != nil {
return nil, err
}
return resp.Id, nil
}, m.queryPrimary)
switch err {
case nil:
return &resp, nil
case sqlc.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultUserModel) FindOneByName(name string) (*User, error) {
userNameKey := fmt.Sprintf("%s%v", cacheUserNamePrefix, name)
var resp User
err := m.QueryRowIndex(&resp, userNameKey, m.formatPrimary, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
query := fmt.Sprintf("select %s from %s where name = ? limit 1", userRows, m.table)
if err := conn.QueryRow(&resp, query, name); err != nil {
return nil, err
}
return resp.Id, nil
}, m.queryPrimary)
switch err {
case nil:
return &resp, nil
case sqlc.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultUserModel) FindOneByMobile(mobile string) (*User, error) {
userMobileKey := fmt.Sprintf("%s%v", cacheUserMobilePrefix, mobile)
var resp User
err := m.QueryRowIndex(&resp, userMobileKey, m.formatPrimary, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
query := fmt.Sprintf("select %s from %s where mobile = ? limit 1", userRows, m.table)
if err := conn.QueryRow(&resp, query, mobile); err != nil {
return nil, err
}
return resp.Id, nil
}, m.queryPrimary)
switch err {
case nil:
return &resp, nil
case sqlc.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultUserModel) Update(data User) error {
userIdKey := fmt.Sprintf("%s%v", cacheUserIdPrefix, data.Id)
_, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set %s where id = ?", m.table, userRowsWithPlaceHolder)
return conn.Exec(query, data.User, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname, data.Id)
}, userIdKey)
return err
}
func (m *defaultUserModel) Delete(id int64) error {
data, err := m.FindOne(id)
if err != nil {
return err
}
userIdKey := fmt.Sprintf("%s%v", cacheUserIdPrefix, id)
userKey := fmt.Sprintf("%s%v", cacheUserPrefix, data.User)
userNameKey := fmt.Sprintf("%s%v", cacheUserNamePrefix, data.Name)
userMobileKey := fmt.Sprintf("%s%v", cacheUserMobilePrefix, data.Mobile)
_, err = m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("delete from %s where id = ?", m.table)
return conn.Exec(query, id)
}, userIdKey, userKey, userNameKey, userMobileKey)
return err
}
func (m *defaultUserModel) formatPrimary(primary interface{}) string {
return fmt.Sprintf("%s%v", cacheUserIdPrefix, primary)
}
func (m *defaultUserModel) queryPrimary(conn sqlx.SqlConn, v, primary interface{}) error {
query := fmt.Sprintf("select %s from %s where id = ? limit 1", userRows, m.table)
return conn.QueryRow(v, query, primary)
}
import (
"database/sql"
"fmt"
"strings"
"time"
"github.com/tal-tech/go-zero/core/stores/cache"
"github.com/tal-tech/go-zero/core/stores/sqlc"
"github.com/tal-tech/go-zero/core/stores/sqlx"
"github.com/tal-tech/go-zero/core/stringx"
"github.com/tal-tech/go-zero/tools/goctl/model/sql/builderx"
)
var (
userFieldNames = builderx.FieldNames(&User{})
userRows = strings.Join(userFieldNames, ",")
userRowsExpectAutoSet = strings.Join(stringx.Remove(userFieldNames, "id", "create_time", "update_time"), ",")
userRowsWithPlaceHolder = strings.Join(stringx.Remove(userFieldNames, "id", "create_time", "update_time"), "=?,") + "=?"
cacheUserIdPrefix = "cache#User#id#"
cacheUserNamePrefix = "cache#User#name#"
cacheUserMobilePrefix = "cache#User#mobile#"
)
type (
UserModel struct {
sqlc.CachedConn
table string
}
User struct {
Id int64 `db:"id"`
Name string `db:"name"` // 用户名称
Password string `db:"password"` // 用户密码
Mobile string `db:"mobile"` // 手机号
Gender string `db:"gender"` // 男|女|未公开
Nickname string `db:"nickname"` // 用户昵称
CreateTime time.Time `db:"create_time"`
UpdateTime time.Time `db:"update_time"`
}
)
func NewUserModel(conn sqlx.SqlConn, c cache.CacheConf) *UserModel {
return &UserModel{
CachedConn: sqlc.NewConn(conn, c),
table: "user",
}
}
func (m *UserModel) Insert(data User) (sql.Result, error) {
userNameKey := fmt.Sprintf("%s%v", cacheUserNamePrefix, data.Name)
userMobileKey := fmt.Sprintf("%s%v", cacheUserMobilePrefix, data.Mobile)
ret, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?)", m.table, userRowsExpectAutoSet)
return conn.Exec(query, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname)
}, userNameKey, userMobileKey)
return ret, err
}
func (m *UserModel) FindOne(id int64) (*User, error) {
userIdKey := fmt.Sprintf("%s%v", cacheUserIdPrefix, id)
var resp User
err := m.QueryRow(&resp, userIdKey, func(conn sqlx.SqlConn, v interface{}) error {
query := fmt.Sprintf("select %s from %s where id = ? limit 1", userRows, m.table)
return conn.QueryRow(v, query, id)
})
switch err {
case nil:
return &resp, nil
case sqlc.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *UserModel) FindOneByName(name string) (*User, error) {
userNameKey := fmt.Sprintf("%s%v", cacheUserNamePrefix, name)
var resp User
err := m.QueryRowIndex(&resp, userNameKey, m.formatPrimary, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
query := fmt.Sprintf("select %s from %s where name = ? limit 1", userRows, m.table)
if err := conn.QueryRow(&resp, query, name); err != nil {
return nil, err
}
return resp.Id, nil
}, m.queryPrimary)
switch err {
case nil:
return &resp, nil
case sqlc.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *UserModel) FindOneByMobile(mobile string) (*User, error) {
userMobileKey := fmt.Sprintf("%s%v", cacheUserMobilePrefix, mobile)
var resp User
err := m.QueryRowIndex(&resp, userMobileKey, m.formatPrimary, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
query := fmt.Sprintf("select %s from %s where mobile = ? limit 1", userRows, m.table)
if err := conn.QueryRow(&resp, query, mobile); err != nil {
return nil, err
}
return resp.Id, nil
}, m.queryPrimary)
switch err {
case nil:
return &resp, nil
case sqlc.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *UserModel) Update(data User) error {
userIdKey := fmt.Sprintf("%s%v", cacheUserIdPrefix, data.Id)
_, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set %s where id = ?", m.table, userRowsWithPlaceHolder)
return conn.Exec(query, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname, data.Id)
}, userIdKey)
return err
}
func (m *UserModel) Delete(id int64) error {
data, err := m.FindOne(id)
if err != nil {
return err
}
userMobileKey := fmt.Sprintf("%s%v", cacheUserMobilePrefix, data.Mobile)
userIdKey := fmt.Sprintf("%s%v", cacheUserIdPrefix, id)
userNameKey := fmt.Sprintf("%s%v", cacheUserNamePrefix, data.Name)
_, err = m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("delete from %s where id = ?", m.table)
return conn.Exec(query, id)
}, userMobileKey, userIdKey, userNameKey)
return err
}
func (m *UserModel) formatPrimary(primary interface{}) string {
return fmt.Sprintf("%s%v", cacheUserIdPrefix, primary)
}
func (m *UserModel) queryPrimary(conn sqlx.SqlConn, v, primary interface{}) error {
query := fmt.Sprintf("select %s from %s where id = ? limit 1", userRows, m.table)
return conn.QueryRow(v, query, primary)
}
``` ```
## 用法 ## 用法
@ -211,25 +246,24 @@ OPTIONS:
* ddl * ddl
```shell script ```shell script
goctl model mysql -src={patterns} -dir={dir} -cache=true goctl model mysql -src={patterns} -dir={dir} -cache
``` ```
help help
``` ```
NAME: NAME:
goctl model mysql ddl - generate mysql model from ddl goctl model mysql ddl - generate mysql model from ddl
USAGE: USAGE:
goctl model mysql ddl [command options] [arguments...] goctl model mysql ddl [command options] [arguments...]
OPTIONS: OPTIONS:
--src value, -s value the path or path globbing patterns of the ddl --src value, -s value the path or path globbing patterns of the ddl
--dir value, -d value the target dir --dir value, -d value the target dir
--style value the file naming style, lower|camel|underline,default is lower --style value the file naming format, see [https://github.com/tal-tech/go-zero/tree/master/tools/goctl/config/readme.md]
--cache, -c generate code with cache [optional] --cache, -c generate code with cache [optional]
--idea for idea plugin [optional] --idea for idea plugin [optional]
``` ```
* datasource * datasource
@ -242,18 +276,19 @@ OPTIONS:
``` ```
NAME: NAME:
goctl model mysql datasource - generate model from datasource goctl model mysql datasource - generate model from datasource
USAGE:
goctl model mysql datasource [command options] [arguments...]
OPTIONS:
--url value the data source of database,like "root:password@tcp(127.0.0.1:3306)/database
--table value, -t value the table or table globbing patterns in the database
--cache, -c generate code with cache [optional]
--dir value, -d value the target dir
--style value the file naming format, see [https://github.com/tal-tech/go-zero/tree/master/tools/goctl/config/readme.md]
--idea for idea plugin [optional]
USAGE:
goctl model mysql datasource [command options] [arguments...]
OPTIONS:
--url value the data source of database,like "root:password@tcp(127.0.0.1:3306)/database
--table value, -t value the table or table globbing patterns in the database
--cache, -c generate code with cache [optional]
--dir value, -d value the target dir
--style value the file naming style, lower|camel|snake, default is lower
--idea for idea plugin [optional]
``` ```
@ -281,13 +316,13 @@ OPTIONS:
* ddl * ddl
```shell script ```shell script
goctl model -src={patterns} -dir={dir} -cache=false goctl model -src={patterns} -dir={dir}
``` ```
* datasource * datasource
```shell script ```shell script
goctl model mysql datasource -url={datasource} -table={patterns} -dir={dir} -cache=false goctl model mysql datasource -url={datasource} -table={patterns} -dir={dir}
``` ```
生成代码仅基本的CURD结构。 生成代码仅基本的CURD结构。

@ -39,7 +39,6 @@ func MysqlDDL(ctx *cli.Context) error {
if err != nil { if err != nil {
return err return err
} }
return fromDDl(src, dir, cfg, cache, idea) return fromDDl(src, dir, cfg, cache, idea)
} }

@ -2,7 +2,7 @@
# generate model with cache from ddl # generate model with cache from ddl
fromDDL: fromDDL:
goctl model mysql ddl -src="./sql/*.sql" -dir="./sql/model/user" -c goctl model mysql ddl -src="./sql/*.sql" -dir="./sql/model/user" -cache
# generate model with cache from data source # generate model with cache from data source
@ -12,4 +12,4 @@ datasource=127.0.0.1:3306
database=gozero database=gozero
fromDataSource: fromDataSource:
goctl model mysql datasource -url="$(user):$(password)@tcp($(datasource))/$(database)" -table="*" -dir ./model/cache -c -style camel goctl model mysql datasource -url="$(user):$(password)@tcp($(datasource))/$(database)" -table="*" -dir ./model/cache -c -style gozero

@ -1,6 +1,7 @@
-- 用户表 -- -- 用户表 --
CREATE TABLE `user` ( CREATE TABLE `user` (
`id` bigint(10) NOT NULL AUTO_INCREMENT, `id` bigint(10) NOT NULL AUTO_INCREMENT,
`user` varchar(50) NOT NULL DEFAULT '' COMMENT '用户',
`name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户名称', `name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户名称',
`password` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户密码', `password` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户密码',
`mobile` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '手机号', `mobile` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '手机号',
@ -10,6 +11,7 @@ CREATE TABLE `user` (
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `name_index` (`name`), UNIQUE KEY `name_index` (`name`),
UNIQUE KEY `user_index` (`user`),
UNIQUE KEY `mobile_index` (`mobile`) UNIQUE KEY `mobile_index` (`mobile`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

@ -9,7 +9,7 @@ import (
"github.com/tal-tech/go-zero/tools/goctl/util/stringx" "github.com/tal-tech/go-zero/tools/goctl/util/stringx"
) )
func genDelete(table Table, withCache bool) (string, error) { func genDelete(table Table, withCache bool) (string, string, error) {
keySet := collection.NewSet() keySet := collection.NewSet()
keyVariableSet := collection.NewSet() keyVariableSet := collection.NewSet()
for fieldName, key := range table.CacheKey { for fieldName, key := range table.CacheKey {
@ -24,7 +24,7 @@ func genDelete(table Table, withCache bool) (string, error) {
camel := table.Name.ToCamel() camel := table.Name.ToCamel()
text, err := util.LoadTemplate(category, deleteTemplateFile, template.Delete) text, err := util.LoadTemplate(category, deleteTemplateFile, template.Delete)
if err != nil { if err != nil {
return "", err return "", "", err
} }
output, err := util.With("delete"). output, err := util.With("delete").
@ -40,8 +40,23 @@ func genDelete(table Table, withCache bool) (string, error) {
"keyValues": strings.Join(keyVariableSet.KeysStr(), ", "), "keyValues": strings.Join(keyVariableSet.KeysStr(), ", "),
}) })
if err != nil { if err != nil {
return "", err return "", "", err
} }
return output.String(), nil // interface method
text, err = util.LoadTemplate(category, deleteMethodTemplateFile, template.DeleteMethod)
if err != nil {
return "", "", err
}
deleteMethodOut, err := util.With("deleteMethod").
Parse(text).
Execute(map[string]interface{}{
"lowerStartCamelPrimaryKey": stringx.From(table.PrimaryKey.Name.ToCamel()).UnTitle(),
"dataType": table.PrimaryKey.DataType,
})
if err != nil {
return "", "", err
}
return output.String(), deleteMethodOut.String(), nil
} }

@ -6,11 +6,11 @@ import (
"github.com/tal-tech/go-zero/tools/goctl/util/stringx" "github.com/tal-tech/go-zero/tools/goctl/util/stringx"
) )
func genFindOne(table Table, withCache bool) (string, error) { func genFindOne(table Table, withCache bool) (string, string, error) {
camel := table.Name.ToCamel() camel := table.Name.ToCamel()
text, err := util.LoadTemplate(category, findOneTemplateFile, template.FindOne) text, err := util.LoadTemplate(category, findOneTemplateFile, template.FindOne)
if err != nil { if err != nil {
return "", err return "", "", err
} }
output, err := util.With("findOne"). output, err := util.With("findOne").
@ -26,8 +26,23 @@ func genFindOne(table Table, withCache bool) (string, error) {
"cacheKeyVariable": table.CacheKey[table.PrimaryKey.Name.Source()].Variable, "cacheKeyVariable": table.CacheKey[table.PrimaryKey.Name.Source()].Variable,
}) })
if err != nil { if err != nil {
return "", err return "", "", err
} }
return output.String(), nil text, err = util.LoadTemplate(category, findOneMethodTemplateFile, template.FindOneMethod)
if err != nil {
return "", "", err
}
findOneMethod, err := util.With("findOneMethod").
Parse(text).
Execute(map[string]interface{}{
"upperStartCamelObject": camel,
"lowerStartCamelPrimaryKey": stringx.From(table.PrimaryKey.Name.ToCamel()).UnTitle(),
"dataType": table.PrimaryKey.DataType,
})
if err != nil {
return "", "", err
}
return output.String(), findOneMethod.String(), nil
} }

@ -9,10 +9,16 @@ import (
"github.com/tal-tech/go-zero/tools/goctl/util/stringx" "github.com/tal-tech/go-zero/tools/goctl/util/stringx"
) )
func genFindOneByField(table Table, withCache bool) (string, string, error) { type findOneCode struct {
findOneMethod string
findOneInterfaceMethod string
cacheExtra string
}
func genFindOneByField(table Table, withCache bool) (*findOneCode, error) {
text, err := util.LoadTemplate(category, findOneByFieldTemplateFile, template.FindOneByField) text, err := util.LoadTemplate(category, findOneByFieldTemplateFile, template.FindOneByField)
if err != nil { if err != nil {
return "", "", err return nil, err
} }
t := util.With("findOneByField").Parse(text) t := util.With("findOneByField").Parse(text)
@ -36,15 +42,40 @@ func genFindOneByField(table Table, withCache bool) (string, string, error) {
"originalField": field.Name.Source(), "originalField": field.Name.Source(),
}) })
if err != nil { if err != nil {
return "", "", err return nil, err
} }
list = append(list, output.String()) list = append(list, output.String())
} }
text, err = util.LoadTemplate(category, findOneByFieldMethodTemplateFile, template.FindOneByFieldMethod)
if err != nil {
return nil, err
}
t = util.With("findOneByFieldMethod").Parse(text)
var listMethod []string
for _, field := range table.Fields {
if field.IsPrimaryKey || !field.IsUniqueKey {
continue
}
camelFieldName := field.Name.ToCamel()
output, err := t.Execute(map[string]interface{}{
"upperStartCamelObject": camelTableName,
"upperField": camelFieldName,
"in": fmt.Sprintf("%s %s", stringx.From(camelFieldName).UnTitle(), field.DataType),
})
if err != nil {
return nil, err
}
listMethod = append(listMethod, output.String())
}
if withCache { if withCache {
text, err := util.LoadTemplate(category, findOneByFieldExtraMethodTemplateFile, template.FindOneByFieldExtraMethod) text, err := util.LoadTemplate(category, findOneByFieldExtraMethodTemplateFile, template.FindOneByFieldExtraMethod)
if err != nil { if err != nil {
return "", "", err return nil, err
} }
out, err := util.With("findOneByFieldExtraMethod").Parse(text).Execute(map[string]interface{}{ out, err := util.With("findOneByFieldExtraMethod").Parse(text).Execute(map[string]interface{}{
@ -54,11 +85,18 @@ func genFindOneByField(table Table, withCache bool) (string, string, error) {
"originalPrimaryField": table.PrimaryKey.Name.Source(), "originalPrimaryField": table.PrimaryKey.Name.Source(),
}) })
if err != nil { if err != nil {
return "", "", err return nil, err
} }
return strings.Join(list, "\n"), out.String(), nil return &findOneCode{
findOneMethod: strings.Join(list, util.NL),
findOneInterfaceMethod: strings.Join(listMethod, util.NL),
cacheExtra: out.String(),
}, nil
} }
return strings.Join(list, "\n"), "", nil
return &findOneCode{
findOneMethod: strings.Join(list, util.NL),
findOneInterfaceMethod: strings.Join(listMethod, util.NL),
}, nil
} }

@ -11,6 +11,7 @@ import (
"github.com/tal-tech/go-zero/tools/goctl/model/sql/model" "github.com/tal-tech/go-zero/tools/goctl/model/sql/model"
"github.com/tal-tech/go-zero/tools/goctl/model/sql/parser" "github.com/tal-tech/go-zero/tools/goctl/model/sql/parser"
"github.com/tal-tech/go-zero/tools/goctl/model/sql/template" "github.com/tal-tech/go-zero/tools/goctl/model/sql/template"
modelutil "github.com/tal-tech/go-zero/tools/goctl/model/sql/util"
"github.com/tal-tech/go-zero/tools/goctl/util" "github.com/tal-tech/go-zero/tools/goctl/util"
"github.com/tal-tech/go-zero/tools/goctl/util/console" "github.com/tal-tech/go-zero/tools/goctl/util/console"
"github.com/tal-tech/go-zero/tools/goctl/util/format" "github.com/tal-tech/go-zero/tools/goctl/util/format"
@ -222,39 +223,41 @@ func (g *defaultGenerator) genModel(in parser.Table, withCache bool) (string, er
return "", err return "", err
} }
typesCode, err := genTypes(table, withCache) insertCode, insertCodeMethod, err := genInsert(table, withCache)
if err != nil { if err != nil {
return "", err return "", err
} }
newCode, err := genNew(table, withCache) var findCode = make([]string, 0)
findOneCode, findOneCodeMethod, err := genFindOne(table, withCache)
if err != nil { if err != nil {
return "", err return "", err
} }
insertCode, err := genInsert(table, withCache) ret, err := genFindOneByField(table, withCache)
if err != nil { if err != nil {
return "", err return "", err
} }
var findCode = make([]string, 0) findCode = append(findCode, findOneCode, ret.findOneMethod)
findOneCode, err := genFindOne(table, withCache) updateCode, updateCodeMethod, err := genUpdate(table, withCache)
if err != nil { if err != nil {
return "", err return "", err
} }
findOneByFieldCode, extraMethod, err := genFindOneByField(table, withCache) deleteCode, deleteCodeMethod, err := genDelete(table, withCache)
if err != nil { if err != nil {
return "", err return "", err
} }
findCode = append(findCode, findOneCode, findOneByFieldCode) var list []string
updateCode, err := genUpdate(table, withCache) list = append(list, insertCodeMethod, findOneCodeMethod, ret.findOneInterfaceMethod, updateCodeMethod, deleteCodeMethod)
typesCode, err := genTypes(table, strings.Join(modelutil.TrimStringSlice(list), util.NL), withCache)
if err != nil { if err != nil {
return "", err return "", err
} }
deleteCode, err := genDelete(table, withCache) newCode, err := genNew(table, withCache)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -269,7 +272,7 @@ func (g *defaultGenerator) genModel(in parser.Table, withCache bool) (string, er
"find": strings.Join(findCode, "\n"), "find": strings.Join(findCode, "\n"),
"update": updateCode, "update": updateCode,
"delete": deleteCode, "delete": deleteCode,
"extraMethod": extraMethod, "extraMethod": ret.cacheExtra,
}) })
if err != nil { if err != nil {
return "", err return "", err

@ -9,7 +9,7 @@ import (
"github.com/tal-tech/go-zero/tools/goctl/util/stringx" "github.com/tal-tech/go-zero/tools/goctl/util/stringx"
) )
func genInsert(table Table, withCache bool) (string, error) { func genInsert(table Table, withCache bool) (string, string, error) {
keySet := collection.NewSet() keySet := collection.NewSet()
keyVariableSet := collection.NewSet() keyVariableSet := collection.NewSet()
for fieldName, key := range table.CacheKey { for fieldName, key := range table.CacheKey {
@ -36,7 +36,7 @@ func genInsert(table Table, withCache bool) (string, error) {
camel := table.Name.ToCamel() camel := table.Name.ToCamel()
text, err := util.LoadTemplate(category, insertTemplateFile, template.Insert) text, err := util.LoadTemplate(category, insertTemplateFile, template.Insert)
if err != nil { if err != nil {
return "", err return "", "", err
} }
output, err := util.With("insert"). output, err := util.With("insert").
@ -52,8 +52,23 @@ func genInsert(table Table, withCache bool) (string, error) {
"keyValues": strings.Join(keyVariableSet.KeysStr(), ", "), "keyValues": strings.Join(keyVariableSet.KeysStr(), ", "),
}) })
if err != nil { if err != nil {
return "", err return "", "", err
} }
return output.String(), nil // interface method
text, err = util.LoadTemplate(category, insertTemplateMethodFile, template.InsertMethod)
if err != nil {
return "", "", err
}
insertMethodOutput, err := util.With("insertMethod").
Parse(text).
Execute(map[string]interface{}{
"upperStartCamelObject": camel,
})
if err != nil {
return "", "", err
}
return output.String(), insertMethodOutput.String(), nil
} }

@ -2,6 +2,7 @@ package gen
import ( import (
"fmt" "fmt"
"strings"
"github.com/tal-tech/go-zero/tools/goctl/model/sql/parser" "github.com/tal-tech/go-zero/tools/goctl/model/sql/parser"
"github.com/tal-tech/go-zero/tools/goctl/util/stringx" "github.com/tal-tech/go-zero/tools/goctl/util/stringx"
@ -33,8 +34,14 @@ func genCacheKeys(table parser.Table) (map[string]Key, error) {
camelFieldName := field.Name.ToCamel() camelFieldName := field.Name.ToCamel()
lowerStartCamelFieldName := stringx.From(camelFieldName).UnTitle() lowerStartCamelFieldName := stringx.From(camelFieldName).UnTitle()
left := fmt.Sprintf("cache%s%sPrefix", camelTableName, camelFieldName) left := fmt.Sprintf("cache%s%sPrefix", camelTableName, camelFieldName)
if strings.ToLower(camelFieldName) == strings.ToLower(camelTableName) {
left = fmt.Sprintf("cache%sPrefix", camelTableName)
}
right := fmt.Sprintf("cache#%s#%s#", camelTableName, lowerStartCamelFieldName) right := fmt.Sprintf("cache#%s#%s#", camelTableName, lowerStartCamelFieldName)
variable := fmt.Sprintf("%s%sKey", lowerStartCamelTableName, camelFieldName) variable := fmt.Sprintf("%s%sKey", lowerStartCamelTableName, camelFieldName)
if strings.ToLower(lowerStartCamelTableName) == strings.ToLower(camelFieldName) {
variable = fmt.Sprintf("%sKey", lowerStartCamelTableName)
}
m[field.Name.Source()] = Key{ m[field.Name.Source()] = Key{
VarExpression: fmt.Sprintf(`%s = "%s"`, left, right), VarExpression: fmt.Sprintf(`%s = "%s"`, left, right),
Left: left, Left: left,

@ -11,31 +11,40 @@ import (
const ( const (
category = "model" category = "model"
deleteTemplateFile = "delete.tpl" deleteTemplateFile = "delete.tpl"
deleteMethodTemplateFile = "interface-delete.tpl"
fieldTemplateFile = "filed.tpl" fieldTemplateFile = "filed.tpl"
findOneTemplateFile = "find-one.tpl" findOneTemplateFile = "find-one.tpl"
findOneMethodTemplateFile = "interface-find-one.tpl"
findOneByFieldTemplateFile = "find-one-by-field.tpl" findOneByFieldTemplateFile = "find-one-by-field.tpl"
findOneByFieldMethodTemplateFile = "interface-find-one-by-field.tpl"
findOneByFieldExtraMethodTemplateFile = "find-one-by-filed-extra-method.tpl" findOneByFieldExtraMethodTemplateFile = "find-one-by-filed-extra-method.tpl"
importsTemplateFile = "import.tpl" importsTemplateFile = "import.tpl"
importsWithNoCacheTemplateFile = "import-no-cache.tpl" importsWithNoCacheTemplateFile = "import-no-cache.tpl"
insertTemplateFile = "insert.tpl" insertTemplateFile = "insert.tpl"
insertTemplateMethodFile = "interface-insert.tpl"
modelTemplateFile = "model.tpl" modelTemplateFile = "model.tpl"
modelNewTemplateFile = "model-new.tpl" modelNewTemplateFile = "model-new.tpl"
tagTemplateFile = "tag.tpl" tagTemplateFile = "tag.tpl"
typesTemplateFile = "types.tpl" typesTemplateFile = "types.tpl"
updateTemplateFile = "update.tpl" updateTemplateFile = "update.tpl"
updateMethodTemplateFile = "interface-update.tpl"
varTemplateFile = "var.tpl" varTemplateFile = "var.tpl"
errTemplateFile = "err.tpl" errTemplateFile = "err.tpl"
) )
var templates = map[string]string{ var templates = map[string]string{
deleteTemplateFile: template.Delete, deleteTemplateFile: template.Delete,
deleteMethodTemplateFile: template.DeleteMethod,
fieldTemplateFile: template.Field, fieldTemplateFile: template.Field,
findOneTemplateFile: template.FindOne, findOneTemplateFile: template.FindOne,
findOneMethodTemplateFile: template.FindOneMethod,
findOneByFieldTemplateFile: template.FindOneByField, findOneByFieldTemplateFile: template.FindOneByField,
findOneByFieldMethodTemplateFile: template.FindOneByFieldMethod,
findOneByFieldExtraMethodTemplateFile: template.FindOneByFieldExtraMethod, findOneByFieldExtraMethodTemplateFile: template.FindOneByFieldExtraMethod,
importsTemplateFile: template.Imports, importsTemplateFile: template.Imports,
importsWithNoCacheTemplateFile: template.ImportsNoCache, importsWithNoCacheTemplateFile: template.ImportsNoCache,
insertTemplateFile: template.Insert, insertTemplateFile: template.Insert,
insertTemplateMethodFile: template.InsertMethod,
modelTemplateFile: template.Model, modelTemplateFile: template.Model,
modelNewTemplateFile: template.New, modelNewTemplateFile: template.New,
tagTemplateFile: template.Tag, tagTemplateFile: template.Tag,

@ -5,7 +5,7 @@ import (
"github.com/tal-tech/go-zero/tools/goctl/util" "github.com/tal-tech/go-zero/tools/goctl/util"
) )
func genTypes(table Table, withCache bool) (string, error) { func genTypes(table Table, methods string, withCache bool) (string, error) {
fields := table.Fields fields := table.Fields
fieldsString, err := genFields(fields) fieldsString, err := genFields(fields)
if err != nil { if err != nil {
@ -21,6 +21,7 @@ func genTypes(table Table, withCache bool) (string, error) {
Parse(text). Parse(text).
Execute(map[string]interface{}{ Execute(map[string]interface{}{
"withCache": withCache, "withCache": withCache,
"method": methods,
"upperStartCamelObject": table.Name.ToCamel(), "upperStartCamelObject": table.Name.ToCamel(),
"fields": fieldsString, "fields": fieldsString,
}) })

@ -8,7 +8,7 @@ import (
"github.com/tal-tech/go-zero/tools/goctl/util/stringx" "github.com/tal-tech/go-zero/tools/goctl/util/stringx"
) )
func genUpdate(table Table, withCache bool) (string, error) { func genUpdate(table Table, withCache bool) (string, string, error) {
expressionValues := make([]string, 0) expressionValues := make([]string, 0)
for _, filed := range table.Fields { for _, filed := range table.Fields {
camel := filed.Name.ToCamel() camel := filed.Name.ToCamel()
@ -24,7 +24,7 @@ func genUpdate(table Table, withCache bool) (string, error) {
camelTableName := table.Name.ToCamel() camelTableName := table.Name.ToCamel()
text, err := util.LoadTemplate(category, updateTemplateFile, template.Update) text, err := util.LoadTemplate(category, updateTemplateFile, template.Update)
if err != nil { if err != nil {
return "", err return "", "", err
} }
output, err := util.With("update"). output, err := util.With("update").
@ -39,8 +39,23 @@ func genUpdate(table Table, withCache bool) (string, error) {
"expressionValues": strings.Join(expressionValues, ", "), "expressionValues": strings.Join(expressionValues, ", "),
}) })
if err != nil { if err != nil {
return "", nil return "", "", nil
} }
return output.String(), nil // update interface method
text, err = util.LoadTemplate(category, updateMethodTemplateFile, template.UpdateMethod)
if err != nil {
return "", "", err
}
updateMethodOutput, err := util.With("updateMethod").
Parse(text).
Execute(map[string]interface{}{
"upperStartCamelObject": camelTableName,
})
if err != nil {
return "", "", nil
}
return output.String(), updateMethodOutput.String(), nil
} }

@ -76,6 +76,9 @@ func TestConvertColumn(t *testing.T) {
assert.Nil(t, err) assert.Nil(t, err)
assert.True(t, table.PrimaryKey.AutoIncrement && table.PrimaryKey.IsPrimaryKey) assert.True(t, table.PrimaryKey.AutoIncrement && table.PrimaryKey.IsPrimaryKey)
assert.Equal(t, "id", table.PrimaryKey.Name.Source()) assert.Equal(t, "id", table.PrimaryKey.Name.Source())
assert.Equal(t, "mobile", table.Fields[1].Name.Source()) for _, item := range table.Fields {
assert.True(t, table.Fields[1].IsUniqueKey) if item.Name.Source() == "mobile" {
assert.True(t, item.IsUniqueKey)
}
}
} }

@ -1,7 +1,7 @@
package template package template
var Delete = ` var Delete = `
func (m *{{.upperStartCamelObject}}Model) Delete({{.lowerStartCamelPrimaryKey}} {{.dataType}}) error { func (m *default{{.upperStartCamelObject}}Model) Delete({{.lowerStartCamelPrimaryKey}} {{.dataType}}) error {
{{if .withCache}}{{if .containsIndexCache}}data, err:=m.FindOne({{.lowerStartCamelPrimaryKey}}) {{if .withCache}}{{if .containsIndexCache}}data, err:=m.FindOne({{.lowerStartCamelPrimaryKey}})
if err!=nil{ if err!=nil{
return err return err
@ -16,3 +16,5 @@ func (m *{{.upperStartCamelObject}}Model) Delete({{.lowerStartCamelPrimaryKey}}
return err return err
} }
` `
var DeleteMethod = `Delete({{.lowerStartCamelPrimaryKey}} {{.dataType}}) error`

@ -2,7 +2,7 @@ package template
// 通过id查询 // 通过id查询
var FindOne = ` var FindOne = `
func (m *{{.upperStartCamelObject}}Model) FindOne({{.lowerStartCamelPrimaryKey}} {{.dataType}}) (*{{.upperStartCamelObject}}, error) { func (m *default{{.upperStartCamelObject}}Model) FindOne({{.lowerStartCamelPrimaryKey}} {{.dataType}}) (*{{.upperStartCamelObject}}, error) {
{{if .withCache}}{{.cacheKey}} {{if .withCache}}{{.cacheKey}}
var resp {{.upperStartCamelObject}} var resp {{.upperStartCamelObject}}
err := m.QueryRow(&resp, {{.cacheKeyVariable}}, func(conn sqlx.SqlConn, v interface{}) error { err := m.QueryRow(&resp, {{.cacheKeyVariable}}, func(conn sqlx.SqlConn, v interface{}) error {
@ -32,7 +32,7 @@ func (m *{{.upperStartCamelObject}}Model) FindOne({{.lowerStartCamelPrimaryKey}}
// 通过指定字段查询 // 通过指定字段查询
var FindOneByField = ` var FindOneByField = `
func (m *{{.upperStartCamelObject}}Model) FindOneBy{{.upperField}}({{.in}}) (*{{.upperStartCamelObject}}, error) { func (m *default{{.upperStartCamelObject}}Model) FindOneBy{{.upperField}}({{.in}}) (*{{.upperStartCamelObject}}, error) {
{{if .withCache}}{{.cacheKey}} {{if .withCache}}{{.cacheKey}}
var resp {{.upperStartCamelObject}} var resp {{.upperStartCamelObject}}
err := m.QueryRowIndex(&resp, {{.cacheKeyVariable}}, m.formatPrimary, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) { err := m.QueryRowIndex(&resp, {{.cacheKeyVariable}}, m.formatPrimary, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
@ -64,12 +64,15 @@ func (m *{{.upperStartCamelObject}}Model) FindOneBy{{.upperField}}({{.in}}) (*{{
}{{end}} }{{end}}
` `
var FindOneByFieldExtraMethod = ` var FindOneByFieldExtraMethod = `
func (m *{{.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)
} }
func (m *{{.upperStartCamelObject}}Model) queryPrimary(conn sqlx.SqlConn, v, primary interface{}) error { func (m *default{{.upperStartCamelObject}}Model) queryPrimary(conn sqlx.SqlConn, v, primary interface{}) error {
query := fmt.Sprintf("select %s from %s where {{.originalPrimaryField}} = ? limit 1", {{.lowerStartCamelObject}}Rows, m.table ) query := fmt.Sprintf("select %s from %s where {{.originalPrimaryField}} = ? limit 1", {{.lowerStartCamelObject}}Rows, m.table )
return conn.QueryRow(v, query, primary) return conn.QueryRow(v, query, primary)
} }
` `
var FindOneMethod = `FindOne({{.lowerStartCamelPrimaryKey}} {{.dataType}}) (*{{.upperStartCamelObject}}, error)`
var FindOneByFieldMethod = `FindOneBy{{.upperField}}({{.in}}) (*{{.upperStartCamelObject}}, error) `

@ -1,7 +1,7 @@
package template package template
var Insert = ` var Insert = `
func (m *{{.upperStartCamelObject}}Model) Insert(data {{.upperStartCamelObject}}) (sql.Result,error) { func (m *default{{.upperStartCamelObject}}Model) Insert(data {{.upperStartCamelObject}}) (sql.Result,error) {
{{if .withCache}}{{if .containsIndexCache}}{{.keys}} {{if .withCache}}{{if .containsIndexCache}}{{.keys}}
ret, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) { ret, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("insert into %s (%s) values ({{.expression}})", m.table, {{.lowerStartCamelObject}}RowsExpectAutoSet) query := fmt.Sprintf("insert into %s (%s) values ({{.expression}})", m.table, {{.lowerStartCamelObject}}RowsExpectAutoSet)
@ -13,3 +13,5 @@ func (m *{{.upperStartCamelObject}}Model) Insert(data {{.upperStartCamelObject}}
return ret,err return ret,err
} }
` `
var InsertMethod = `Insert(data {{.upperStartCamelObject}}) (sql.Result,error)`

@ -1,8 +1,8 @@
package template package template
var New = ` var 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}}) {{.upperStartCamelObject}}Model {
return &{{.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}}",
} }

@ -2,7 +2,11 @@ package template
var Types = ` var Types = `
type ( type (
{{.upperStartCamelObject}}Model struct { {{.upperStartCamelObject}}Model interface{
{{.method}}
}
default{{.upperStartCamelObject}}Model struct {
{{if .withCache}}sqlc.CachedConn{{else}}conn sqlx.SqlConn{{end}} {{if .withCache}}sqlc.CachedConn{{else}}conn sqlx.SqlConn{{end}}
table string table string
} }

@ -1,7 +1,7 @@
package template package template
var Update = ` var Update = `
func (m *{{.upperStartCamelObject}}Model) Update(data {{.upperStartCamelObject}}) error { func (m *default{{.upperStartCamelObject}}Model) Update(data {{.upperStartCamelObject}}) error {
{{if .withCache}}{{.primaryCacheKey}} {{if .withCache}}{{.primaryCacheKey}}
_, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) { _, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set %s where {{.originalPrimaryKey}} = ?", m.table, {{.lowerStartCamelObject}}RowsWithPlaceHolder) query := fmt.Sprintf("update %s set %s where {{.originalPrimaryKey}} = ?", m.table, {{.lowerStartCamelObject}}RowsWithPlaceHolder)
@ -11,3 +11,5 @@ func (m *{{.upperStartCamelObject}}Model) Update(data {{.upperStartCamelObject}}
return err return err
} }
` `
var UpdateMethod = `Update(data {{.upperStartCamelObject}}) error`

@ -0,0 +1,12 @@
package util
func TrimStringSlice(list []string) []string {
var out []string
for _, item := range list {
if len(item) == 0 {
continue
}
out = append(out, item)
}
return out
}
Loading…
Cancel
Save