dynamic.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. package rest
  2. import (
  3. "git.nspix.com/golang/rest/v3/inflector"
  4. "gorm.io/gorm"
  5. "reflect"
  6. "strconv"
  7. "strings"
  8. )
  9. type (
  10. //Dynamic 实现动态结构体的操作
  11. Dynamic struct {
  12. moduleName string
  13. tableName string
  14. schemas []*Schema
  15. fields []reflect.StructField
  16. }
  17. Dialector struct {
  18. gorm.Dialector
  19. tableName string
  20. }
  21. Migrator struct {
  22. gorm.Migrator
  23. tableName string
  24. }
  25. )
  26. func (d *Dialector) Migrator(db *gorm.DB) gorm.Migrator {
  27. migrator := d.Dialector.Migrator(db)
  28. if db.Statement != nil {
  29. db.Statement.Table = d.tableName
  30. }
  31. return newDynamicMigrator(d.tableName, migrator)
  32. }
  33. func (m *Migrator) HasTable(dst interface{}) bool {
  34. return m.Migrator.HasTable(m.tableName)
  35. }
  36. func newDynamicDialector(tableName string, dialector gorm.Dialector) *Dialector {
  37. return &Dialector{dialector, tableName}
  38. }
  39. func newDynamicMigrator(tableName string, migrator gorm.Migrator) *Migrator {
  40. mig := &Migrator{migrator, tableName}
  41. return mig
  42. }
  43. //Interface 返回结构体的实体结构
  44. func (d *Dynamic) Interface() interface{} {
  45. refValue := reflect.New(d.Type())
  46. return refValue.Interface()
  47. }
  48. //Type 返回结构体类型
  49. func (d *Dynamic) Type() reflect.Type {
  50. reflectType := reflect.StructOf(d.fields)
  51. return reflectType
  52. }
  53. //Slice 返回结构体slice类型
  54. func (d *Dynamic) Slice() reflect.Type {
  55. return reflect.SliceOf(d.Type())
  56. }
  57. //Reset 重置表结构
  58. func (d *Dynamic) Reset(schemas []*Schema) {
  59. d.fields = make([]reflect.StructField, 0, 10)
  60. d.schemas = schemas
  61. d.buildField(schemas)
  62. }
  63. //ModuleName 模块名称
  64. func (d *Dynamic) ModuleName() string {
  65. return d.moduleName
  66. }
  67. //TableName 表名称
  68. func (d *Dynamic) TableName() string {
  69. return d.tableName
  70. }
  71. //typeOfSchema 通过schema生成结构体的类型
  72. func (d *Dynamic) typeOfSchema(schema *Schema) reflect.Type {
  73. switch schema.Type {
  74. case TypeBoolean:
  75. return reflect.TypeOf(uint8(0))
  76. case TypeInteger:
  77. return reflect.TypeOf(int64(0))
  78. case TypeFloat:
  79. return reflect.TypeOf(float64(0))
  80. default:
  81. return reflect.TypeOf("")
  82. }
  83. }
  84. //tagOfSchema 通过schema生成结构体的tag
  85. func (d *Dynamic) tagOfSchema(schema *Schema) reflect.StructTag {
  86. var sb strings.Builder
  87. var tags = make(map[string][]string)
  88. tags["json"] = []string{schema.Column}
  89. tags["yaml"] = []string{schema.Column}
  90. gormPairs := make([]string, 0, 5)
  91. if schema.IsPrimaryKey == 1 {
  92. gormPairs = append(gormPairs, "primaryKey")
  93. }
  94. switch schema.Type {
  95. case TypeInteger, TypeFloat:
  96. gormPairs = append(gormPairs, "not null")
  97. if schema.IsPrimaryKey == 0 {
  98. gormPairs = append(gormPairs, "default:0")
  99. }
  100. case TypeBoolean:
  101. gormPairs = append(gormPairs, "not null")
  102. case TypeString:
  103. if schema.Rule.Max > 0 {
  104. gormPairs = append(gormPairs, "size:"+strconv.Itoa(schema.Rule.Max*2))
  105. } else {
  106. gormPairs = append(gormPairs, "size:1024")
  107. }
  108. gormPairs = append(gormPairs, "not null")
  109. gormPairs = append(gormPairs, "default:''")
  110. }
  111. if schema.Rule.Unique {
  112. gormPairs = append(gormPairs, "unique")
  113. }
  114. gormPairs = append(gormPairs, "comment:"+schema.Label)
  115. tags["gorm"] = gormPairs
  116. for tag, pairs := range tags {
  117. sb.WriteString(tag + ":\"")
  118. sb.WriteString(strings.Join(pairs, ";"))
  119. sb.WriteString("\" ")
  120. }
  121. return reflect.StructTag(sb.String())
  122. }
  123. //buildField 通过schema构建字段
  124. func (d *Dynamic) buildField(schemas []*Schema) {
  125. for _, schema := range schemas {
  126. d.moduleName = schema.ModuleName
  127. d.tableName = schema.TableName
  128. field := reflect.StructField{
  129. Name: inflector.Camelize(schema.Column),
  130. Type: d.typeOfSchema(schema),
  131. Tag: d.tagOfSchema(schema),
  132. }
  133. d.fields = append(d.fields, field)
  134. }
  135. }
  136. func NewDynamic(schemas []*Schema) *Dynamic {
  137. model := &Dynamic{}
  138. model.Reset(schemas)
  139. return model
  140. }