github.com/unionj-cloud/go-doudou/v2@v2.3.5/toolkit/gormgen/internal/model/tbl_column.go (about) 1 package model 2 3 import ( 4 "fmt" 5 "reflect" 6 "strings" 7 8 "github.com/unionj-cloud/go-doudou/v2/toolkit/gormgen/field" 9 "gorm.io/gorm" 10 ) 11 12 // Column table column's info 13 type Column struct { 14 gorm.ColumnType 15 TableName string `gorm:"column:TABLE_NAME"` 16 Indexes []*Index `gorm:"-"` 17 UseScanType bool `gorm:"-"` 18 dataTypeMap map[string]func(columnType gorm.ColumnType) (dataType string) `gorm:"-"` 19 jsonTagNS func(columnName string) string `gorm:"-"` 20 } 21 22 // SetDataTypeMap set data type map 23 func (c *Column) SetDataTypeMap(m map[string]func(columnType gorm.ColumnType) (dataType string)) { 24 c.dataTypeMap = m 25 } 26 27 // GetDataType get data type 28 func (c *Column) GetDataType() (fieldtype string) { 29 if mapping, ok := c.dataTypeMap[c.DatabaseTypeName()]; ok { 30 return mapping(c.ColumnType) 31 } 32 if c.UseScanType && c.ScanType() != nil { 33 return c.ScanType().String() 34 } 35 return dataType.Get(c.DatabaseTypeName(), c.columnType()) 36 } 37 38 // WithNS with name strategy 39 func (c *Column) WithNS(jsonTagNS func(columnName string) string) { 40 c.jsonTagNS = jsonTagNS 41 if c.jsonTagNS == nil { 42 c.jsonTagNS = func(n string) string { return n } 43 } 44 } 45 46 // ToField convert to field 47 func (c *Column) ToField(nullable, coverable, signable bool) *Field { 48 fieldType := c.GetDataType() 49 if signable && strings.Contains(c.columnType(), "unsigned") && strings.HasPrefix(fieldType, "int") { 50 fieldType = "u" + fieldType 51 } 52 switch { 53 case c.Name() == "deleted_at" && fieldType == "time.Time": 54 fieldType = "gorm.DeletedAt" 55 case coverable && c.needDefaultTag(c.defaultTagValue()): 56 fieldType = "*" + fieldType 57 case nullable: 58 if n, ok := c.Nullable(); ok && n { 59 fieldType = "*" + fieldType 60 } 61 } 62 63 var comment string 64 if c, ok := c.Comment(); ok { 65 comment = c 66 } 67 68 isPriKey, ok := c.PrimaryKey() 69 70 return &Field{ 71 Name: c.Name(), 72 Type: fieldType, 73 ColumnName: c.Name(), 74 MultilineComment: c.multilineComment(), 75 GORMTag: c.buildGormTag(), 76 Tag: map[string]string{field.TagKeyJson: c.jsonTagNS(c.Name())}, 77 ColumnComment: comment, 78 PriKey: ok && isPriKey, 79 } 80 } 81 82 func (c *Column) multilineComment() bool { 83 cm, ok := c.Comment() 84 return ok && strings.Contains(cm, "\n") 85 } 86 87 func (c *Column) buildGormTag() field.GormTag { 88 tag := field.GormTag{ 89 field.TagKeyGormColumn: []string{c.Name()}, 90 field.TagKeyGormType: []string{c.columnType()}, 91 } 92 isPriKey, ok := c.PrimaryKey() 93 isValidPriKey := ok && isPriKey 94 if isValidPriKey { 95 tag.Set(field.TagKeyGormPrimaryKey, "") 96 if at, ok := c.AutoIncrement(); ok { 97 tag.Set(field.TagKeyGormAutoIncrement, fmt.Sprintf("%t", at)) 98 } 99 } else if n, ok := c.Nullable(); ok && !n { 100 tag.Set(field.TagKeyGormNotNull, "") 101 } 102 103 for _, idx := range c.Indexes { 104 if idx == nil { 105 continue 106 } 107 if pk, _ := idx.PrimaryKey(); pk { //ignore PrimaryKey 108 continue 109 } 110 if uniq, _ := idx.Unique(); uniq { 111 tag.Append(field.TagKeyGormUniqueIndex, fmt.Sprintf("%s,priority:%d", idx.Name(), idx.Priority)) 112 } else { 113 tag.Append(field.TagKeyGormIndex, fmt.Sprintf("%s,priority:%d", idx.Name(), idx.Priority)) 114 } 115 } 116 117 if dtValue := c.defaultTagValue(); c.needDefaultTag(dtValue) { // cannot set default tag for primary key 118 tag.Set(field.TagKeyGormDefault, dtValue) 119 } 120 if comment, ok := c.Comment(); ok && comment != "" { 121 if c.multilineComment() { 122 comment = strings.ReplaceAll(comment, "\n", "\\n") 123 } 124 tag.Set(field.TagKeyGormComment, comment) 125 } 126 return tag 127 } 128 129 // needDefaultTag check if default tag needed 130 func (c *Column) needDefaultTag(defaultTagValue string) bool { 131 if defaultTagValue == "" { 132 return false 133 } 134 switch c.ScanType().Kind() { 135 case reflect.Bool: 136 return defaultTagValue != "false" 137 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64: 138 return defaultTagValue != "0" 139 case reflect.String: 140 return defaultTagValue != "" 141 case reflect.Struct: 142 return strings.Trim(defaultTagValue, "'0:- ") != "" 143 } 144 return c.Name() != "created_at" && c.Name() != "updated_at" 145 } 146 147 // defaultTagValue return gorm default tag's value 148 func (c *Column) defaultTagValue() string { 149 value, ok := c.DefaultValue() 150 if !ok { 151 return "" 152 } 153 if value != "" && strings.TrimSpace(value) == "" { 154 return "'" + value + "'" 155 } 156 return value 157 } 158 159 func (c *Column) columnType() (v string) { 160 if cl, ok := c.ColumnType.ColumnType(); ok { 161 return cl 162 } 163 return c.DatabaseTypeName() 164 }