1 Star 0 Fork 1

go-genie/sqlx

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
model.go 6.21 KB
一键复制 编辑 原始数据 按行查看 历史
文兄 提交于 2025-06-17 16:11 +08:00 . init
package generator
import (
"fmt"
"gitee.com/go-genie/sqlx"
"gitee.com/go-genie/sqlx/datatypes"
reflectx "gitee.com/go-genie/xx/reflect"
typesx "gitee.com/go-genie/xx/types"
"go/types"
"reflect"
"strconv"
"strings"
"gitee.com/go-genie/codegen"
"gitee.com/go-genie/packagesx"
"gitee.com/go-genie/sqlx/builder"
)
func NewModel(pkg *packagesx.Package, typeName *types.TypeName, comments string, cfg *Config) *Model {
m := Model{}
m.Config = cfg
m.Config.SetDefaults()
m.TypeName = typeName
m.Table = builder.T(cfg.TableName)
p := pkg.Pkg(typeName.Pkg().Path())
forEachStructField(typeName.Type().Underlying().Underlying().(*types.Struct), func(structVal *types.Var, columnName string, tagValue string) {
col := builder.Col(columnName).Field(structVal.Name()).Type("", tagValue)
for id, o := range p.TypesInfo.Defs {
if o == structVal {
doc := pkg.CommentsOf(id)
rel, lines := parseColRelFromComment(doc)
if rel != "" {
relPath := strings.Split(rel, ".")
if len(relPath) != 2 {
continue
}
col.Relation = relPath
}
if len(lines) > 0 {
col.Comment = lines[0]
col.Description = lines
}
}
}
m.addColumn(col, structVal)
})
m.HasDeletedAt = m.Table.F(m.FieldKeyDeletedAt) != nil
m.HasCreatedAt = m.Table.F(m.FieldKeyCreatedAt) != nil
m.HasUpdatedAt = m.Table.F(m.FieldKeyUpdatedAt) != nil
keys, lines := parseKeysFromDoc(comments)
m.Keys = keys
if len(lines) > 0 {
m.Description = lines
}
if m.HasDeletedAt {
m.Keys.PatchUniqueIndexesWithSoftDelete(m.FieldKeyDeletedAt)
}
m.Keys.Bind(m.Table)
if autoIncrementCol := m.Table.AutoIncrement(); autoIncrementCol != nil {
m.HasAutoIncrement = true
m.FieldKeyAutoIncrement = autoIncrementCol.FieldName
}
return &m
}
func NewModelsFromDataBase(s *sqlx.Database) []*Model {
models := make([]*Model, 0)
s.Tables.Range(func(t *builder.Table, index int) {
model := &Model{
TypeName: types.NewTypeName(0, nil, codegen.LowerCamelCase(t.Name)[1:], (&types.Struct{}).Underlying()),
Table: &builder.Table{},
Keys: &Keys{
Primary: []string{},
Indexes: make(builder.Indexes),
UniqueIndexes: make(builder.Indexes),
},
Fields: make(map[string]*types.Var),
}
t.Columns.Range(func(col *builder.Column, index int) {
model.addField(col)
if col.Name == "f_created_at" {
model.HasCreatedAt = true
}
if col.Name == "f_updated_at" {
model.HasUpdatedAt = true
}
if col.Name == "f_deleted_at" {
model.HasDeletedAt = true
}
})
t.Keys.Range(func(key *builder.Key, index int) {
if strings.Contains(key.Name, "pkey") {
if model.Primary != nil {
model.Primary = append(model.Primary, strings.Split(key.Def.Expr[1:len(key.Def.Expr)-1], ",")...)
} else {
model.Primary = strings.Split(key.Def.Expr[1:len(key.Def.Expr)-1], ",")
}
} else {
switch key.IsUnique {
case true:
model.UniqueIndexes[key.Name] = strings.Split(key.Def.Expr[1:len(key.Def.Expr)-1], ",")
case false:
model.Indexes[key.Name] = strings.Split(key.Def.Expr[1:len(key.Def.Expr)-1], ",")
}
}
})
if t.AutoIncrement() != nil {
model.HasAutoIncrement = true
model.FieldKeyAutoIncrement = t.AutoIncrement().Name
}
models = append(models, model)
})
return models
}
type Model struct {
*types.TypeName
*Config
*Keys
*builder.Table
Fields map[string]*types.Var
StructFields []*builder.StructField
FieldKeyAutoIncrement string
HasDeletedAt bool
HasCreatedAt bool
HasUpdatedAt bool
HasAutoIncrement bool
}
func (m *Model) addColumn(col *builder.Column, tpe *types.Var) {
m.Table.Columns.Add(col)
if m.Fields == nil {
m.Fields = map[string]*types.Var{}
}
m.Fields[col.FieldName] = tpe
}
func (m *Model) addField(col *builder.Column) {
if m.StructFields == nil {
m.StructFields = make([]*builder.StructField, 0)
}
m.StructFields = append(m.StructFields, &builder.StructField{
Name: codegen.LowerCamelCase(col.Name)[1:],
FieldName: col.Name,
Type: typesx.PtrTo(typesx.FromRType(m.BasicDataType(col.ColumnType))),
Tags: m.ColumnTag(col),
ColumnType: *col.ColumnType,
})
}
func (m *Model) BasicDataType(columnType *builder.ColumnType) reflect.Type {
switch columnType.DataType {
case "bigserial", "bigint":
return reflect.TypeOf(uint64(0))
case "integer", "serial", "smallint":
return reflect.TypeOf(uint32(0))
case "double precision", "real", "numeric":
return reflect.TypeOf(float64(0))
case "varchar", "text", "character varying", "character", "json":
return reflect.TypeOf(string(""))
case "timestamp with time zone", "timestamp without time zone":
return reflect.TypeOf(datatypes.PgTimestampTz{})
case "boolean":
return reflect.TypeOf(bool(false))
case "USER-DEFINED", "ARRAY":
return reflect.TypeOf([]byte{})
}
panic(fmt.Errorf("unsupport type %s", columnType.DataType))
}
func (m *Model) ColumnTag(column *builder.Column) map[string]reflectx.StructTag {
t := make(map[string]reflectx.StructTag)
t["db"] = reflectx.StructTag(column.Name)
if column.ColumnType.AutoIncrement {
t["db"] = t["db"] + ",autoincrement"
t["json"] = "-"
} else {
t["json"] = reflectx.StructTag(codegen.LowerCamelCase(codegen.LowerCamelCase(column.Name)[1:]))
}
if column.ColumnType.Length > 0 {
t["db"] = t["db"] + reflectx.StructTag(",size="+strconv.FormatUint(column.ColumnType.Length, 10))
}
if column.ColumnType.Null {
t["db"] = t["db"] + ",null"
}
if column.ColumnType.Default != nil {
t["db"] = t["db"] + reflectx.StructTag(",default="+strings.Split(*column.ColumnType.Default, "::")[0])
}
return t
}
func (m *Model) WriteTo(file *codegen.File) {
m.WriteTableKeyInterfaces(file)
if m.WithTableName {
m.WriteTableName(file)
}
if m.WithTableInterfaces {
m.WriteTableInterfaces(file)
}
if m.WithMethods {
m.WriteCRUD(file)
m.WriteList(file)
m.WriteCount(file)
m.WriteBatchList(file)
}
}
func (m *Model) Type() codegen.SnippetType {
return codegen.Type(m.StructName)
}
func (m *Model) IteratorType() codegen.SnippetType {
return codegen.Type(m.StructName + "Iterator")
}
func (m *Model) PtrType() codegen.SnippetType {
return codegen.Star(m.Type())
}
func (m *Model) VarTable() string {
return m.StructName + "Table"
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/go-genie/sqlx.git
git@gitee.com:go-genie/sqlx.git
go-genie
sqlx
sqlx
v1.1.3

搜索帮助