column.go 8.7 KB
Newer Older
aaronchen2k2k's avatar
aaronchen2k2k 已提交
1 2 3
package helper

import (
4 5
	"fmt"
	"github.com/asaskevich/govalidator"
aaronchen2k2k's avatar
aaronchen2k2k 已提交
6
	consts "github.com/easysoft/zendata/internal/pkg/const"
7 8 9
	"math/rand"
	"regexp"
	"strconv"
aaronchen2k2k's avatar
aaronchen2k2k 已提交
10
	"strings"
11
	"time"
aaronchen2k2k's avatar
aaronchen2k2k 已提交
12 13
)

14 15
func GenerateFieldDefByMetadata(metadata string, param string, name string, records []interface{}) (info FieldTypeInfo) {
	GetColumnType(metadata, name, records, &info)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
16

17 18 19
	if info.ColumnType == consts.Varchar && info.VarcharType != "" {
		generateDefByVarcharType(param, &info)
		return
aaronchen2k2k's avatar
aaronchen2k2k 已提交
20
	}
21 22 23 24
	if info.ColumnType == consts.Json {
		generateDefForJson(records, &info)
		return
	}
aaronchen2k2k's avatar
aaronchen2k2k 已提交
25

26
	GenDefByColumnType(param, &info)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
27 28 29 30

	return
}

31 32 33 34 35 36 37 38 39 40 41
func generateDefForJson(records []interface{}, info *FieldTypeInfo) {
	rang := Json
	if len(records) > 0 {
		rang = fmt.Sprintf("%v", records[0])
	}

	info.Rang = rang
	info.Format = "json"
}

func generateDefByVarcharType(param string, info *FieldTypeInfo) {
42 43 44 45 46
	if info.Rang != "" || info.VarcharType == "" {
		return
	}

	if info.VarcharType == consts.Username {
47 48
		info.From = "name.enaccount.v1.yaml"
		info.Use = "common_underline"
49 50

	} else if info.VarcharType == consts.Email {
51 52
		info.From = "email.v1.yaml"
		info.Use = "western_with_esp"
53 54

	} else if info.VarcharType == consts.Url {
55 56 57
		info.From = "domain.domain.v1.yaml"
		info.Use = "letters_at_cn"
		info.Prefix = "https://"
58 59

	} else if info.VarcharType == consts.Ip {
60 61
		info.From = "ip.v1.yaml"
		info.Use = "privateB"
62 63

	} else if info.VarcharType == consts.Mac {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
64
		info.Format = "mac()"
65 66

	} else if info.VarcharType == consts.CreditCard {
67
		info.Format = "credit_card('amex')"
68 69

	} else if info.VarcharType == consts.IdCard {
70
		info.Format = "id_card()"
71 72

	} else if info.VarcharType == consts.MobileNumber {
73 74
		info.From = "phone.v1.yaml"
		info.Use = "cellphone"
75 76

	} else if info.VarcharType == consts.TelNumber {
77 78
		info.From = "phone.v1.yaml"
		info.Use = "telephone_china"
79 80

	} else if info.VarcharType == consts.Token {
81
		info.Format = "token()"
82 83

	} else if info.VarcharType == consts.Uuid {
84 85
		info.From = "uuid.v1.yaml"
		info.Use = "length32_random"
86 87

	} else if info.VarcharType == consts.JsonStr {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
88
		info.Format = "json()"
89 90

	} else if info.VarcharType == consts.Md5 {
91 92
		info.Rang = "1-100"
		info.Format = "md5"
93
	}
94

aaronchen2k2k's avatar
aaronchen2k2k 已提交
95 96 97
	return
}

98
func GetColumnType(metaType string, name string, records []interface{}, info *FieldTypeInfo) {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
99 100 101 102 103 104
	metaType = strings.ToLower(metaType)

	if metaType == "integer" {
		metaType = "int"
	}

105 106 107 108 109
	info.ColumnType = consts.ColumnType(metaType)

	if info.ColumnType == consts.Varchar {
		info.VarcharType = GetVarcharTypeByName(name)
	}
aaronchen2k2k's avatar
aaronchen2k2k 已提交
110

111 112
	if info.ColumnType == consts.Varchar && info.VarcharType == "" && len(records) > 0 {
		info.VarcharType = GetVarcharTypeByRecords(records)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
113 114
	}

115 116 117 118 119 120 121
	if info.ColumnType == consts.Float || info.ColumnType == consts.Double {
		GetPrecisionByRecords(records, info)
	}

	SetIsNum(info)
	if info.IsNum {
		GetSignByRecords(records, info)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
122 123 124 125 126
	}

	return
}

127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
func SetIsNum(info *FieldTypeInfo) {
	info.IsNum = info.ColumnType == consts.Tinyint || info.ColumnType == consts.Smallint ||
		info.ColumnType == consts.Mediumint || info.ColumnType == consts.Int || info.ColumnType == consts.Bigint ||
		info.ColumnType == consts.Float || info.ColumnType == consts.Double
}

func GetSignByRecords(records []interface{}, info *FieldTypeInfo) {
	if len(records) == 0 {
		return
	}
	num := getRandNum(len(records))
	computerPrecision(records[num], info)

	num = getRandNum(len(records))
	computerPrecision(records[num], info)

	num = getRandNum(len(records))
	computerPrecision(records[num], info)
}
func GetPrecisionByRecords(records []interface{}, info *FieldTypeInfo) {
	if len(records) == 0 {
		return
	}

	num := getRandNum(len(records))
	computerSign(records[num], info)

	num = getRandNum(len(records))
	computerSign(records[num], info)

	num = getRandNum(len(records))
	computerSign(records[num], info)
}
func computerPrecision(val interface{}, info *FieldTypeInfo) {
	str := fmt.Sprintf("%v", val)

	index := strings.LastIndex(str, ".")
	subStr := str[index+1:]

	info.Precision = len(subStr)
}
func computerSign(val interface{}, info *FieldTypeInfo) {
	str := fmt.Sprintf("%v", val)
	float, _ := strconv.ParseFloat(str, 64)

	info.HasSign = info.HasSign || float < 0
aaronchen2k2k's avatar
aaronchen2k2k 已提交
173 174
}

aaronchen2k2k's avatar
aaronchen2k2k 已提交
175 176
func GetVarcharTypeByName(name string) (ret consts.VarcharType) {
	ret = consts.Empty
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191

	if regexp.MustCompile(`(user).*(name)`).MatchString(name) {
		ret = consts.Username
	} else if regexp.MustCompile(`(phone|number)`).MatchString(name) {
		if regexp.MustCompile(`(tel)`).MatchString(name) {
			ret = consts.TelNumber
		} else { // default use mobile phone
			ret = consts.MobileNumber
		}
	} else if regexp.MustCompile(`(email)`).MatchString(name) {
		ret = consts.Email
	} else if regexp.MustCompile(`(url)`).MatchString(name) {
		ret = consts.Url
	} else if regexp.MustCompile(`(ip)`).MatchString(name) {
		ret = consts.Ip
192 193
	} else if regexp.MustCompile(`(mac).*(address)`).MatchString(name) {
		ret = consts.Mac
194 195 196 197 198 199 200 201
	} else if regexp.MustCompile(`(creditcard)`).MatchString(name) {
		ret = consts.CreditCard
	} else if regexp.MustCompile(`(idcard)`).MatchString(name) {
		ret = consts.IdCard
	} else if regexp.MustCompile(`(token)`).MatchString(name) {
		ret = consts.Token
	}

aaronchen2k2k's avatar
aaronchen2k2k 已提交
202 203 204
	return
}

205
func GetVarcharTypeByRecords(records []interface{}) (ret consts.VarcharType) {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
206
	ret = consts.Empty
207 208 209 210 211 212 213 214 215

	if len(records) == 0 {
		return
	}

	val := fmt.Sprintf("%v", records[0])

	if govalidator.IsEmail(val) {
		ret = consts.Email
aaronchen2k2k's avatar
aaronchen2k2k 已提交
216

217 218
	} else if govalidator.IsCreditCard(val) {
		ret = consts.CreditCard
aaronchen2k2k's avatar
aaronchen2k2k 已提交
219

220 221
	} else if govalidator.IsMAC(val) {
		ret = consts.Mac
aaronchen2k2k's avatar
aaronchen2k2k 已提交
222

223 224
	} else if govalidator.IsUUID(val) {
		ret = consts.Uuid
225

226 227 228 229 230
	} else if govalidator.IsMD5(val) {
		ret = consts.Md5

	} else if IsMobilePhone(val) {
		ret = consts.MobileNumber
aaronchen2k2k's avatar
aaronchen2k2k 已提交
231

232 233
	} else if IsTelPhone(val) {
		ret = consts.TelNumber
aaronchen2k2k's avatar
aaronchen2k2k 已提交
234

235 236
	} else if IsIDCard(val) {
		ret = consts.IdCard
aaronchen2k2k's avatar
aaronchen2k2k 已提交
237

238 239
	} else if govalidator.IsURL(val) {
		ret = consts.Url
aaronchen2k2k's avatar
aaronchen2k2k 已提交
240 241 242

	} else if govalidator.IsJSON(val) {
		ret = consts.JsonStr
243 244
	}

aaronchen2k2k's avatar
aaronchen2k2k 已提交
245 246 247 248
	return
}

type FieldTypeInfo struct {
249 250 251 252 253 254 255
	ColumnType  consts.ColumnType
	VarcharType consts.VarcharType

	IsNum     bool
	Precision int
	HasSign   bool

aaronchen2k2k's avatar
aaronchen2k2k 已提交
256 257 258 259 260 261 262 263 264 265
	Note    string
	Rang    string
	Loop    string
	Loopfix string
	Type    string
	Format  string
	From    string
	Use     string
	Select  string
	Prefix  string
aaronchen2k2k's avatar
aaronchen2k2k 已提交
266 267
}

268 269
func GenDefByColumnType(param string, ret *FieldTypeInfo) {
	switch ret.ColumnType {
270
	// int
271
	case "bit":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
272
		ret.Rang, ret.Note = GenBit()
273
	case "tinyint":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
274
		ret.Rang, ret.Note = GenTinyint(ret.HasSign)
275
	case "smallint":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
276
		ret.Rang, ret.Note = GenSmallint(ret.HasSign)
277
	case "mediumint":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
278
		ret.Rang, ret.Note = GenMediumint(ret.HasSign)
279
	case "int":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
280
		ret.Rang, ret.Note = GenInt(ret.HasSign)
281
	case "bigint":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
282
		ret.Rang, ret.Note = GenBigint(ret.HasSign)
283 284

	// float
285
	case "float":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
286
		ret.Rang, ret.Note = GenFloat(ret.HasSign)
287
	case "double":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
288
		ret.Rang, ret.Note = GenDouble(ret.HasSign)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
289
	// fixed-point
290
	case "decimal":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
291
		ret.Rang, ret.Note = GenDecimal(ret.HasSign)
292 293

	// string
294
	case "char":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
295 296
		ret.Rang, ret.Loop = GenChar(param)

297
	case "tinytext":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
298 299
		ret.From = "idiom.v1.idiom"
		ret.Select = "word"
300
	case "text":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
301 302
		ret.From = "xiehouyu.v1.xiehouyu"
		ret.Select = "riddle"
303
	case "mediumtext":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
304 305
		ret.From = "joke.v1.joke"
		ret.Select = "content"
306
	case "longtext":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
307 308
		ret.From = "song.v1.song"
		ret.Select = "lyric"
309

aaronchen2k2k's avatar
aaronchen2k2k 已提交
310
	// binary data
311
	case "tinyblob":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
312
		ret.From, ret.Format = GenBin()
313
	case "blob":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
314
		ret.From, ret.Format = GenBin()
315
	case "mediumblob":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
316
		ret.From, ret.Format = GenBin()
317
	case "longblob":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
318
		ret.From, ret.Format = GenBin()
319
	case "binary":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
320
		ret.From, ret.Format = GenBin()
321
	case "varbinary":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
322
		ret.From, ret.Format = GenBin()
323

324 325
	// date and time type
	case "date":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
326
		ret.Rang, ret.Type, ret.Format = GenDate()
327
	case "time":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
328
		ret.Rang, ret.Type, ret.Format = GenTime()
329
	case "year":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
330
		ret.Rang, ret.Type, ret.Format = GenYear()
331
	case "datetime":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
332
		ret.Rang, ret.Type, ret.Format = GenDatetime()
333
	case "timestamp":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
334
		ret.Rang, ret.Type, ret.Format = GenTimestamp()
335

aaronchen2k2k's avatar
aaronchen2k2k 已提交
336
	// other type
337
	case "enum":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
338
		ret.Rang = getEnumValue(param)
339
	case "set":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
340
		ret.Rang, ret.Loop, ret.Loopfix = getSetValue(param)
341 342

	//case "geometry":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
343
	//	ret.Rang = `"geometry"`
344
	//case "point":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
345
	//	ret.Rang = `"point"`
346
	//case "linestring":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
347
	//	ret.Rang = `"linestring"`
348
	//case "polygon":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
349
	//	ret.Rang = `"polygon"`
350
	//case "multipoint":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
351
	//	ret.Rang = `"multipoint"`
352
	//case "multilinestring":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
353
	//	ret.Rang = `"multilinestring"`
354
	//case "multipolygon":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
355
	//	ret.Rang = `"multipolygon"`
356
	//case "geometrycollection":
aaronchen2k2k's avatar
aaronchen2k2k 已提交
357
	//	ret.Rang = `"geometrycollection"`
358

aaronchen2k2k's avatar
aaronchen2k2k 已提交
359 360 361
	default:
	}

362 363 364 365
	return
}

func getEnumValue(param string) (ret string) {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
366
	ret = strings.ReplaceAll(param, "'", "")
367 368 369 370

	return
}

aaronchen2k2k's avatar
aaronchen2k2k 已提交
371
func getSetValue(param string) (ret, loop, loopfix string) {
372 373
	ret = strings.ReplaceAll(param, "'", "")

aaronchen2k2k's avatar
aaronchen2k2k 已提交
374 375 376 377 378 379 380 381
	arr := strings.Split(param, ",")

	start := 1
	if len(arr) > 2 {
		start = 2
	}
	loop = fmt.Sprintf("%d-%d", start, len(arr))

382 383 384 385 386 387 388
	return
}

func getRandNum(num int) (ret int) {
	ret = rand.New(rand.NewSource(time.Now().UnixNano())).Intn(num)

	return
aaronchen2k2k's avatar
aaronchen2k2k 已提交
389
}