github.com/easysoft/zendata@v0.0.0-20240513203326-705bd5a7fd67/internal/pkg/helper/column.go (about) 1 package helper 2 3 import ( 4 "fmt" 5 "math/rand" 6 "regexp" 7 "strconv" 8 "strings" 9 "time" 10 11 "github.com/asaskevich/govalidator" 12 consts "github.com/easysoft/zendata/internal/pkg/const" 13 ) 14 15 func GenerateFieldDefByMetadata(metadata string, param string, name string, records []interface{}) (info FieldTypeInfo) { 16 GetColumnType(metadata, name, records, &info) 17 18 if info.ColumnType == consts.Varchar && info.VarcharType != "" { 19 generateDefByVarcharType(param, &info) 20 return 21 } 22 if info.ColumnType == consts.Json { 23 generateDefForJson(records, &info) 24 return 25 } 26 27 GenDefByColumnType(param, &info) 28 29 return 30 } 31 32 func generateDefForJson(records []interface{}, info *FieldTypeInfo) { 33 rang := Json 34 if len(records) > 0 { 35 rang = fmt.Sprintf("%v", records[0]) 36 } 37 38 info.Rang = rang 39 info.Format = "json" 40 } 41 42 func generateDefByVarcharType(param string, info *FieldTypeInfo) { 43 if info.Rang != "" || info.VarcharType == "" { 44 return 45 } 46 47 if info.VarcharType == consts.Username { 48 info.From = "name.enaccount.v1.yaml" 49 info.Use = "common_underline" 50 51 } else if info.VarcharType == consts.Email { 52 info.From = "email.v1.yaml" 53 info.Use = "western_with_esp" 54 55 } else if info.VarcharType == consts.Url { 56 info.From = "domain.domain.v1.yaml" 57 info.Use = "letters_at_cn" 58 info.Prefix = "https://" 59 60 } else if info.VarcharType == consts.Ip { 61 info.From = "ip.v1.yaml" 62 info.Use = "privateB" 63 64 } else if info.VarcharType == consts.Mac { 65 info.Format = "mac()" 66 67 } else if info.VarcharType == consts.CreditCard { 68 info.Format = "credit_card('amex')" 69 70 } else if info.VarcharType == consts.IdCard { 71 info.Format = "id_card()" 72 73 } else if info.VarcharType == consts.MobileNumber { 74 info.From = "phone.v1.yaml" 75 info.Use = "cellphone" 76 77 } else if info.VarcharType == consts.TelNumber { 78 info.From = "phone.v1.yaml" 79 info.Use = "telephone_china" 80 81 } else if info.VarcharType == consts.Token { 82 info.Format = "token()" 83 84 } else if info.VarcharType == consts.Uuid { 85 info.From = "uuid.v1.yaml" 86 info.Use = "length32_random" 87 88 } else if info.VarcharType == consts.JsonStr { 89 info.Format = "json()" 90 91 } else if info.VarcharType == consts.Md5 { 92 info.Rang = "1-100" 93 info.Format = "md5" 94 } 95 96 return 97 } 98 99 func GetColumnType(metaType string, name string, records []interface{}, info *FieldTypeInfo) { 100 metaType = strings.ToLower(metaType) 101 102 if metaType == "integer" { 103 metaType = "int" 104 } 105 106 info.ColumnType = consts.ColumnType(metaType) 107 108 if info.ColumnType == consts.Varchar { 109 info.VarcharType = GetVarcharTypeByName(name) 110 } 111 112 if info.ColumnType == consts.Varchar && info.VarcharType == "" && len(records) > 0 { 113 info.VarcharType = GetVarcharTypeByRecords(records) 114 } 115 116 if info.ColumnType == consts.Float || info.ColumnType == consts.Double { 117 GetPrecisionByRecords(records, info) 118 } 119 120 SetIsNum(info) 121 if info.IsNum { 122 GetSignByRecords(records, info) 123 } 124 125 return 126 } 127 128 func SetIsNum(info *FieldTypeInfo) { 129 info.IsNum = info.ColumnType == consts.Tinyint || info.ColumnType == consts.Smallint || 130 info.ColumnType == consts.Mediumint || info.ColumnType == consts.Int || info.ColumnType == consts.Bigint || 131 info.ColumnType == consts.Float || info.ColumnType == consts.Double 132 } 133 134 func GetSignByRecords(records []interface{}, info *FieldTypeInfo) { 135 if len(records) == 0 { 136 return 137 } 138 num := getRandNum(len(records)) 139 computerPrecision(records[num], info) 140 141 num = getRandNum(len(records)) 142 computerPrecision(records[num], info) 143 144 num = getRandNum(len(records)) 145 computerPrecision(records[num], info) 146 } 147 func GetPrecisionByRecords(records []interface{}, info *FieldTypeInfo) { 148 if len(records) == 0 { 149 return 150 } 151 152 num := getRandNum(len(records)) 153 computerSign(records[num], info) 154 155 num = getRandNum(len(records)) 156 computerSign(records[num], info) 157 158 num = getRandNum(len(records)) 159 computerSign(records[num], info) 160 } 161 func computerPrecision(val interface{}, info *FieldTypeInfo) { 162 str := fmt.Sprintf("%v", val) 163 164 index := strings.LastIndex(str, ".") 165 subStr := str[index+1:] 166 167 info.Precision = len(subStr) 168 } 169 func computerSign(val interface{}, info *FieldTypeInfo) { 170 str := fmt.Sprintf("%v", val) 171 float, _ := strconv.ParseFloat(str, 64) 172 173 info.HasSign = info.HasSign || float < 0 174 } 175 176 func GetVarcharTypeByName(name string) (ret consts.VarcharType) { 177 ret = consts.Empty 178 179 if regexp.MustCompile(`(user).*(name)`).MatchString(name) { 180 ret = consts.Username 181 } else if regexp.MustCompile(`(phone|number)`).MatchString(name) { 182 if regexp.MustCompile(`(tel)`).MatchString(name) { 183 ret = consts.TelNumber 184 } else { // default use mobile phone 185 ret = consts.MobileNumber 186 } 187 } else if regexp.MustCompile(`(email)`).MatchString(name) { 188 ret = consts.Email 189 } else if regexp.MustCompile(`(url)`).MatchString(name) { 190 ret = consts.Url 191 } else if regexp.MustCompile(`(ip)`).MatchString(name) { 192 ret = consts.Ip 193 } else if regexp.MustCompile(`(mac).*(address)`).MatchString(name) { 194 ret = consts.Mac 195 } else if regexp.MustCompile(`(creditcard)`).MatchString(name) { 196 ret = consts.CreditCard 197 } else if regexp.MustCompile(`(idcard)`).MatchString(name) { 198 ret = consts.IdCard 199 } else if regexp.MustCompile(`(token)`).MatchString(name) { 200 ret = consts.Token 201 } 202 203 return 204 } 205 206 func GetVarcharTypeByRecords(records []interface{}) (ret consts.VarcharType) { 207 ret = consts.Empty 208 209 if len(records) == 0 { 210 return 211 } 212 213 val := fmt.Sprintf("%v", records[0]) 214 215 if govalidator.IsEmail(val) { 216 ret = consts.Email 217 218 } else if govalidator.IsCreditCard(val) { 219 ret = consts.CreditCard 220 221 } else if govalidator.IsMAC(val) { 222 ret = consts.Mac 223 224 } else if govalidator.IsUUID(val) { 225 ret = consts.Uuid 226 227 } else if govalidator.IsMD5(val) { 228 ret = consts.Md5 229 230 } else if IsIDCard(val) { 231 ret = consts.IdCard 232 233 } else if IsMobilePhone(val) { 234 ret = consts.MobileNumber 235 236 } else if IsTelPhone(val) { 237 ret = consts.TelNumber 238 239 } else if govalidator.IsURL(val) { 240 ret = consts.Url 241 242 } else if govalidator.IsJSON(val) { 243 ret = consts.JsonStr 244 } 245 246 return 247 } 248 249 type FieldTypeInfo struct { 250 ColumnType consts.ColumnType 251 VarcharType consts.VarcharType 252 253 IsNum bool 254 Precision int 255 HasSign bool 256 257 Note string 258 Rang string 259 Loop string 260 Loopfix string 261 Type string 262 Format string 263 From string 264 Use string 265 Select string 266 Prefix string 267 } 268 269 func GenDefByColumnType(param string, ret *FieldTypeInfo) { 270 switch ret.ColumnType { 271 // int 272 case "bit": 273 ret.Rang, ret.Note = GenBit() 274 case "tinyint": 275 ret.Rang, ret.Note = GenTinyint(ret.HasSign) 276 case "smallint": 277 ret.Rang, ret.Note = GenSmallint(ret.HasSign) 278 case "mediumint": 279 ret.Rang, ret.Note = GenMediumint(ret.HasSign) 280 case "int": 281 ret.Rang, ret.Note = GenInt(ret.HasSign) 282 case "bigint": 283 ret.Rang, ret.Note = GenBigint(ret.HasSign) 284 285 // float 286 case "float": 287 ret.Rang, ret.Note = GenFloat(ret.HasSign) 288 case "double": 289 ret.Rang, ret.Note = GenDouble(ret.HasSign) 290 // fixed-point 291 case "decimal": 292 ret.Rang, ret.Note = GenDecimal(ret.HasSign) 293 294 // string 295 case "char": 296 ret.Rang, ret.Loop = GenChar(param) 297 298 case "tinytext": 299 ret.From = "idiom.v1.idiom" 300 ret.Select = "word" 301 case "text": 302 ret.From = "xiehouyu.v1.xiehouyu" 303 ret.Select = "riddle" 304 case "mediumtext": 305 ret.From = "joke.v1.joke" 306 ret.Select = "content" 307 case "longtext": 308 ret.From = "song.v1.song" 309 ret.Select = "lyric" 310 311 // binary data 312 case "tinyblob": 313 ret.From, ret.Format = GenBin() 314 case "blob": 315 ret.From, ret.Format = GenBin() 316 case "mediumblob": 317 ret.From, ret.Format = GenBin() 318 case "longblob": 319 ret.From, ret.Format = GenBin() 320 case "binary": 321 ret.From, ret.Format = GenBin() 322 case "varbinary": 323 ret.From, ret.Format = GenBin() 324 325 // date and time type 326 case "date": 327 ret.Rang, ret.Type, ret.Format = GenDate() 328 case "time": 329 ret.Rang, ret.Type, ret.Format = GenTime() 330 case "year": 331 ret.Rang, ret.Type, ret.Format = GenYear() 332 case "datetime": 333 ret.Rang, ret.Type, ret.Format = GenDatetime() 334 case "timestamp": 335 ret.Rang, ret.Type, ret.Format = GenTimestamp() 336 337 // other type 338 case "enum": 339 ret.Rang = getEnumValue(param) 340 case "set": 341 ret.Rang, ret.Loop, ret.Loopfix = getSetValue(param) 342 343 //case "geometry": 344 // ret.Rang = `"geometry"` 345 //case "point": 346 // ret.Rang = `"point"` 347 //case "linestring": 348 // ret.Rang = `"linestring"` 349 //case "polygon": 350 // ret.Rang = `"polygon"` 351 //case "multipoint": 352 // ret.Rang = `"multipoint"` 353 //case "multilinestring": 354 // ret.Rang = `"multilinestring"` 355 //case "multipolygon": 356 // ret.Rang = `"multipolygon"` 357 //case "geometrycollection": 358 // ret.Rang = `"geometrycollection"` 359 360 default: 361 } 362 363 return 364 } 365 366 func getEnumValue(param string) (ret string) { 367 ret = strings.ReplaceAll(param, "'", "") 368 369 return 370 } 371 372 func getSetValue(param string) (ret, loop, loopfix string) { 373 ret = strings.ReplaceAll(param, "'", "") 374 375 arr := strings.Split(param, ",") 376 377 start := 1 378 if len(arr) > 2 { 379 start = 2 380 } 381 loop = fmt.Sprintf("%d-%d", start, len(arr)) 382 383 return 384 } 385 386 func getRandNum(num int) (ret int) { 387 ret = rand.New(rand.NewSource(time.Now().UnixNano())).Intn(num) 388 389 return 390 }