feat: add custom field type mapping support for command gf gen dao (#3498)

This commit is contained in:
CyJaySong
2024-04-25 19:19:09 +08:00
committed by GitHub
parent cc98e5759c
commit 5b7cae78bc
7 changed files with 284 additions and 6 deletions

View File

@ -71,6 +71,7 @@ func Test_Gen_Dao_Default(t *testing.T) {
NoModelComment: false,
Clear: false,
TypeMapping: nil,
FieldMapping: nil,
}
)
err = gutil.FillStructWithDefault(&in)
@ -171,6 +172,7 @@ func Test_Gen_Dao_TypeMapping(t *testing.T) {
Import: "github.com/shopspring/decimal",
},
},
FieldMapping: nil,
}
)
err = gutil.FillStructWithDefault(&in)
@ -213,6 +215,108 @@ func Test_Gen_Dao_TypeMapping(t *testing.T) {
})
}
func Test_Gen_Dao_FieldMapping(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
err error
db = testDB
table = "table_user"
sqlContent = fmt.Sprintf(
gtest.DataContent(`gendao`, `user.tpl.sql`),
table,
)
)
defer dropTableWithDb(db, table)
array := gstr.SplitAndTrim(sqlContent, ";")
for _, v := range array {
if _, err = db.Exec(ctx, v); err != nil {
t.AssertNil(err)
}
}
defer dropTableWithDb(db, table)
var (
path = gfile.Temp(guid.S())
group = "test"
in = gendao.CGenDaoInput{
Path: path,
Link: link,
Tables: "table_user",
TablesEx: "",
Group: group,
Prefix: "",
RemovePrefix: "",
JsonCase: "",
ImportPrefix: "",
DaoPath: "",
DoPath: "",
EntityPath: "",
TplDaoIndexPath: "",
TplDaoInternalPath: "",
TplDaoDoPath: "",
TplDaoEntityPath: "",
StdTime: false,
WithTime: false,
GJsonSupport: false,
OverwriteDao: false,
DescriptionTag: false,
NoJsonTag: false,
NoModelComment: false,
Clear: false,
TypeMapping: map[gendao.DBFieldTypeName]gendao.CustomAttributeType{
"int": {
Type: "int64",
Import: "",
},
},
FieldMapping: map[gendao.DBTableFieldName]gendao.CustomAttributeType{
"table_user.score": {
Type: "decimal.Decimal",
Import: "github.com/shopspring/decimal",
},
},
}
)
err = gutil.FillStructWithDefault(&in)
t.AssertNil(err)
err = gfile.Mkdir(path)
t.AssertNil(err)
// for go mod import path auto retrieve.
err = gfile.Copy(
gtest.DataPath("gendao", "go.mod.txt"),
gfile.Join(path, "go.mod"),
)
t.AssertNil(err)
_, err = gendao.CGenDao{}.Dao(ctx, in)
t.AssertNil(err)
defer gfile.Remove(path)
// files
files, err := gfile.ScanDir(path, "*.go", true)
t.AssertNil(err)
t.Assert(files, []string{
filepath.FromSlash(path + "/dao/internal/table_user.go"),
filepath.FromSlash(path + "/dao/table_user.go"),
filepath.FromSlash(path + "/model/do/table_user.go"),
filepath.FromSlash(path + "/model/entity/table_user.go"),
})
// content
testPath := gtest.DataPath("gendao", "generated_user_field_mapping")
expectFiles := []string{
filepath.FromSlash(testPath + "/dao/internal/table_user.go"),
filepath.FromSlash(testPath + "/dao/table_user.go"),
filepath.FromSlash(testPath + "/model/do/table_user.go"),
filepath.FromSlash(testPath + "/model/entity/table_user.go"),
}
for i, _ := range files {
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
}
})
}
func execSqlFile(db gdb.DB, filePath string, args ...any) error {
sqlContent := fmt.Sprintf(
gfile.GetContents(filePath),
@ -271,6 +375,7 @@ func Test_Gen_Dao_Issue2572(t *testing.T) {
NoModelComment: false,
Clear: false,
TypeMapping: nil,
FieldMapping: nil,
}
)
err = gutil.FillStructWithDefault(&in)
@ -359,6 +464,7 @@ func Test_Gen_Dao_Issue2616(t *testing.T) {
NoModelComment: false,
Clear: false,
TypeMapping: nil,
FieldMapping: nil,
}
)
err = gutil.FillStructWithDefault(&in)
@ -469,6 +575,7 @@ func Test_Gen_Dao_Issue2746(t *testing.T) {
NoModelComment: false,
Clear: false,
TypeMapping: nil,
FieldMapping: nil,
}
)
err = gutil.FillStructWithDefault(&in)

View File

@ -58,6 +58,10 @@ CONFIGURATION SUPPORT
import: github.com/shopspring/decimal
numeric:
type: string
fieldMapping:
table_name.field_name:
type: decimal.Decimal
import: github.com/shopspring/decimal
`
CGenDaoBriefPath = `directory path for generated files`
CGenDaoBriefLink = `database configuration, the same as the ORM configuration of GoFrame`
@ -81,6 +85,7 @@ CONFIGURATION SUPPORT
CGenDaoBriefNoModelComment = `no model comment will be added for each field`
CGenDaoBriefClear = `delete all generated go files that do not exist in database`
CGenDaoBriefTypeMapping = `custom local type mapping for generated struct attributes relevant to fields of table`
CGenDaoBriefFieldMapping = `custom local type mapping for generated struct attributes relevant to specific fields of table`
CGenDaoBriefGroup = `
specifying the configuration group name of database for generated ORM instance,
it's not necessary and the default value is "default"
@ -162,6 +167,7 @@ func init() {
`CGenDaoBriefNoModelComment`: CGenDaoBriefNoModelComment,
`CGenDaoBriefClear`: CGenDaoBriefClear,
`CGenDaoBriefTypeMapping`: CGenDaoBriefTypeMapping,
`CGenDaoBriefFieldMapping`: CGenDaoBriefFieldMapping,
`CGenDaoBriefGroup`: CGenDaoBriefGroup,
`CGenDaoBriefJsonCase`: CGenDaoBriefJsonCase,
`CGenDaoBriefTplDaoIndexPath`: CGenDaoBriefTplDaoIndexPath,
@ -201,8 +207,9 @@ type (
NoModelComment bool `name:"noModelComment" short:"m" brief:"{CGenDaoBriefNoModelComment}" orphan:"true"`
Clear bool `name:"clear" short:"a" brief:"{CGenDaoBriefClear}" orphan:"true"`
TypeMapping map[DBFieldTypeName]CustomAttributeType `name:"typeMapping" short:"y" brief:"{CGenDaoBriefTypeMapping}" orphan:"true"`
genItems *CGenDaoInternalGenItems
TypeMapping map[DBFieldTypeName]CustomAttributeType `name:"typeMapping" short:"y" brief:"{CGenDaoBriefTypeMapping}" orphan:"true"`
FieldMapping map[DBTableFieldName]CustomAttributeType `name:"fieldMapping" short:"fm" brief:"{CGenDaoBriefFieldMapping}" orphan:"true"`
genItems *CGenDaoInternalGenItems
}
CGenDaoOutput struct{}
@ -212,7 +219,7 @@ type (
TableNames []string
NewTableNames []string
}
DBTableFieldName = string
DBFieldTypeName = string
CustomAttributeType struct {
Type string `brief:"custom attribute type name"`
@ -363,7 +370,7 @@ func getImportPartContent(ctx context.Context, source string, isDo bool, appendI
}
// Check and update imports in go.mod
if appendImports != nil && len(appendImports) > 0 {
if len(appendImports) > 0 {
goModPath := utils.GetModPath()
if goModPath == "" {
mlog.Fatal("go.mod not found in current project")
@ -381,8 +388,9 @@ func getImportPartContent(ctx context.Context, source string, isDo bool, appendI
}
}
if !found {
err = gproc.ShellRun(ctx, `go get `+appendImport)
mlog.Fatalf(`%+v`, err)
if err = gproc.ShellRun(ctx, `go get `+appendImport); err != nil {
mlog.Fatalf(`%+v`, err)
}
}
packageImportsArray.Append(fmt.Sprintf(`"%s"`, appendImport))
}

View File

@ -131,6 +131,14 @@ func generateStructFieldDefinition(
for _, v := range removeFieldPrefixArray {
newFiledName = gstr.TrimLeftStr(newFiledName, v, 1)
}
if in.FieldMapping != nil && len(in.FieldMapping) > 0 {
if typeMapping, ok := in.FieldMapping[fmt.Sprintf("%s.%s", in.Tables, newFiledName)]; ok {
localTypeNameStr = typeMapping.Type
appendImport = typeMapping.Import
}
}
attrLines = []string{
" #" + gstr.CaseCamel(newFiledName),
" #" + localTypeNameStr,

View File

@ -0,0 +1,85 @@
// ==========================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// ==========================================================================
package internal
import (
"context"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
)
// TableUserDao is the data access object for table table_user.
type TableUserDao struct {
table string // table is the underlying table name of the DAO.
group string // group is the database configuration group name of current DAO.
columns TableUserColumns // columns contains all the column names of Table for convenient usage.
}
// TableUserColumns defines and stores column names for table table_user.
type TableUserColumns struct {
Id string // User ID
Passport string // User Passport
Password string // User Password
Nickname string // User Nickname
Score string // Total score amount.
CreateAt string // Created Time
UpdateAt string // Updated Time
}
// tableUserColumns holds the columns for table table_user.
var tableUserColumns = TableUserColumns{
Id: "id",
Passport: "passport",
Password: "password",
Nickname: "nickname",
Score: "score",
CreateAt: "create_at",
UpdateAt: "update_at",
}
// NewTableUserDao creates and returns a new DAO object for table data access.
func NewTableUserDao() *TableUserDao {
return &TableUserDao{
group: "test",
table: "table_user",
columns: tableUserColumns,
}
}
// DB retrieves and returns the underlying raw database management object of current DAO.
func (dao *TableUserDao) DB() gdb.DB {
return g.DB(dao.group)
}
// Table returns the table name of current dao.
func (dao *TableUserDao) Table() string {
return dao.table
}
// Columns returns all column names of current dao.
func (dao *TableUserDao) Columns() TableUserColumns {
return dao.columns
}
// Group returns the configuration group name of database of current dao.
func (dao *TableUserDao) Group() string {
return dao.group
}
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
func (dao *TableUserDao) Ctx(ctx context.Context) *gdb.Model {
return dao.DB().Model(dao.table).Safe().Ctx(ctx)
}
// Transaction wraps the transaction logic using function f.
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
// It commits the transaction and returns nil if function f returns nil.
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *TableUserDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -0,0 +1,27 @@
// =================================================================================
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
// =================================================================================
package dao
import (
"for-gendao-test/pkg/dao/internal"
)
// internalTableUserDao is internal type for wrapping internal DAO implements.
type internalTableUserDao = *internal.TableUserDao
// tableUserDao is the data access object for table table_user.
// You can define custom methods on it to extend its functionality as you wish.
type tableUserDao struct {
internalTableUserDao
}
var (
// TableUser is globally public accessible object for table table_user operations.
TableUser = tableUserDao{
internal.NewTableUserDao(),
}
)
// Fill with you ideas below.

View File

@ -0,0 +1,22 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package do
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
)
// TableUser is the golang structure of table table_user for DAO operations like Where/Data.
type TableUser struct {
g.Meta `orm:"table:table_user, do:true"`
Id interface{} // User ID
Passport interface{} // User Passport
Password interface{} // User Password
Nickname interface{} // User Nickname
Score interface{} // Total score amount.
CreateAt *gtime.Time // Created Time
UpdateAt *gtime.Time // Updated Time
}

View File

@ -0,0 +1,21 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package entity
import (
"github.com/gogf/gf/v2/os/gtime"
"github.com/shopspring/decimal"
)
// TableUser is the golang structure for table table_user.
type TableUser struct {
Id int64 `json:"id" orm:"id" ` // User ID
Passport string `json:"passport" orm:"passport" ` // User Passport
Password string `json:"password" orm:"password" ` // User Password
Nickname string `json:"nickname" orm:"nickname" ` // User Nickname
Score decimal.Decimal `json:"score" orm:"score" ` // Total score amount.
CreateAt *gtime.Time `json:"createAt" orm:"create_at" ` // Created Time
UpdateAt *gtime.Time `json:"updateAt" orm:"update_at" ` // Updated Time
}