|
@@ -0,0 +1,158 @@
|
|
|
+package rest
|
|
|
+
|
|
|
+import (
|
|
|
+ "git.nspix.com/golang/rest/v3/inflector"
|
|
|
+ "gorm.io/gorm"
|
|
|
+ "reflect"
|
|
|
+ "strconv"
|
|
|
+ "strings"
|
|
|
+)
|
|
|
+
|
|
|
+type (
|
|
|
+ //Dynamic 实现动态结构体的操作
|
|
|
+ Dynamic struct {
|
|
|
+ moduleName string
|
|
|
+ tableName string
|
|
|
+ schemas []*Schema
|
|
|
+ fields []reflect.StructField
|
|
|
+ }
|
|
|
+
|
|
|
+ Dialector struct {
|
|
|
+ gorm.Dialector
|
|
|
+ tableName string
|
|
|
+ }
|
|
|
+
|
|
|
+ Migrator struct {
|
|
|
+ gorm.Migrator
|
|
|
+ tableName string
|
|
|
+ }
|
|
|
+)
|
|
|
+
|
|
|
+func (d *Dialector) Migrator(db *gorm.DB) gorm.Migrator {
|
|
|
+ migrator := d.Dialector.Migrator(db)
|
|
|
+ if db.Statement != nil {
|
|
|
+ db.Statement.Table = d.tableName
|
|
|
+ }
|
|
|
+ return newDynamicMigrator(d.tableName, migrator)
|
|
|
+}
|
|
|
+
|
|
|
+func (m *Migrator) HasTable(dst interface{}) bool {
|
|
|
+ return m.Migrator.HasTable(m.tableName)
|
|
|
+}
|
|
|
+
|
|
|
+func newDynamicDialector(tableName string, dialector gorm.Dialector) *Dialector {
|
|
|
+ return &Dialector{dialector, tableName}
|
|
|
+}
|
|
|
+
|
|
|
+func newDynamicMigrator(tableName string, migrator gorm.Migrator) *Migrator {
|
|
|
+ mig := &Migrator{migrator, tableName}
|
|
|
+ return mig
|
|
|
+}
|
|
|
+
|
|
|
+//Interface 返回结构体的实体结构
|
|
|
+func (d *Dynamic) Interface() interface{} {
|
|
|
+ refValue := reflect.New(d.Type())
|
|
|
+ return refValue.Interface()
|
|
|
+}
|
|
|
+
|
|
|
+//Type 返回结构体类型
|
|
|
+func (d *Dynamic) Type() reflect.Type {
|
|
|
+ reflectType := reflect.StructOf(d.fields)
|
|
|
+ return reflectType
|
|
|
+}
|
|
|
+
|
|
|
+//Slice 返回结构体slice类型
|
|
|
+func (d *Dynamic) Slice() reflect.Type {
|
|
|
+ return reflect.SliceOf(d.Type())
|
|
|
+}
|
|
|
+
|
|
|
+//Reset 重置表结构
|
|
|
+func (d *Dynamic) Reset(schemas []*Schema) {
|
|
|
+ d.fields = make([]reflect.StructField, 0, 10)
|
|
|
+ d.schemas = schemas
|
|
|
+ d.buildField(schemas)
|
|
|
+}
|
|
|
+
|
|
|
+//ModuleName 模块名称
|
|
|
+func (d *Dynamic) ModuleName() string {
|
|
|
+ return d.moduleName
|
|
|
+}
|
|
|
+
|
|
|
+//TableName 表名称
|
|
|
+func (d *Dynamic) TableName() string {
|
|
|
+ return d.tableName
|
|
|
+}
|
|
|
+
|
|
|
+//typeOfSchema 通过schema生成结构体的类型
|
|
|
+func (d *Dynamic) typeOfSchema(schema *Schema) reflect.Type {
|
|
|
+ switch schema.Type {
|
|
|
+ case TypeBoolean:
|
|
|
+ return reflect.TypeOf(uint8(0))
|
|
|
+ case TypeInteger:
|
|
|
+ return reflect.TypeOf(int64(0))
|
|
|
+ case TypeFloat:
|
|
|
+ return reflect.TypeOf(float64(0))
|
|
|
+ default:
|
|
|
+ return reflect.TypeOf("")
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//tagOfSchema 通过schema生成结构体的tag
|
|
|
+func (d *Dynamic) tagOfSchema(schema *Schema) reflect.StructTag {
|
|
|
+ var sb strings.Builder
|
|
|
+ var tags = make(map[string][]string)
|
|
|
+ tags["json"] = []string{schema.Column}
|
|
|
+ tags["yaml"] = []string{schema.Column}
|
|
|
+ gormPairs := make([]string, 0, 5)
|
|
|
+ if schema.IsPrimaryKey == 1 {
|
|
|
+ gormPairs = append(gormPairs, "primaryKey")
|
|
|
+ }
|
|
|
+ switch schema.Type {
|
|
|
+ case TypeInteger, TypeFloat:
|
|
|
+ gormPairs = append(gormPairs, "not null")
|
|
|
+ if schema.IsPrimaryKey == 0 {
|
|
|
+ gormPairs = append(gormPairs, "default:0")
|
|
|
+ }
|
|
|
+ case TypeBoolean:
|
|
|
+ gormPairs = append(gormPairs, "not null")
|
|
|
+ case TypeString:
|
|
|
+ if schema.Rule.Max > 0 {
|
|
|
+ gormPairs = append(gormPairs, "size:"+strconv.Itoa(schema.Rule.Max*2))
|
|
|
+ } else {
|
|
|
+ gormPairs = append(gormPairs, "size:1024")
|
|
|
+ }
|
|
|
+ gormPairs = append(gormPairs, "not null")
|
|
|
+ gormPairs = append(gormPairs, "default:''")
|
|
|
+ }
|
|
|
+ if schema.Rule.Unique {
|
|
|
+ gormPairs = append(gormPairs, "unique")
|
|
|
+ }
|
|
|
+ gormPairs = append(gormPairs, "comment:"+schema.Label)
|
|
|
+ tags["gorm"] = gormPairs
|
|
|
+ for tag, pairs := range tags {
|
|
|
+ sb.WriteString(tag + ":\"")
|
|
|
+ sb.WriteString(strings.Join(pairs, ";"))
|
|
|
+ sb.WriteString("\" ")
|
|
|
+ }
|
|
|
+ return reflect.StructTag(sb.String())
|
|
|
+}
|
|
|
+
|
|
|
+//buildField 通过schema构建字段
|
|
|
+func (d *Dynamic) buildField(schemas []*Schema) {
|
|
|
+ for _, schema := range schemas {
|
|
|
+ d.moduleName = schema.ModuleName
|
|
|
+ d.tableName = schema.TableName
|
|
|
+ field := reflect.StructField{
|
|
|
+ Name: inflector.Camelize(schema.Column),
|
|
|
+ Type: d.typeOfSchema(schema),
|
|
|
+ Tag: d.tagOfSchema(schema),
|
|
|
+ }
|
|
|
+ d.fields = append(d.fields, field)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func NewDynamic(schemas []*Schema) *Dynamic {
|
|
|
+ model := &Dynamic{}
|
|
|
+ model.Reset(schemas)
|
|
|
+ return model
|
|
|
+}
|