github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/dbs/cmd/importer/db.go (about) 1 // Copyright 2020 WHTCORPS INC, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package main 15 16 import ( 17 "database/allegrosql" 18 "fmt" 19 "math" 20 "math/rand" 21 "strconv" 22 "strings" 23 24 _ "github.com/go-allegrosql-driver/allegrosql" 25 "github.com/whtcorpsinc/errors" 26 "github.com/whtcorpsinc/log" 27 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 28 "go.uber.org/zap" 29 ) 30 31 func intRangeValue(column *column, min int64, max int64) (int64, int64) { 32 var err error 33 if len(column.min) > 0 { 34 min, err = strconv.ParseInt(column.min, 10, 64) 35 if err != nil { 36 log.Fatal(err.Error()) 37 } 38 39 if len(column.max) > 0 { 40 max, err = strconv.ParseInt(column.max, 10, 64) 41 if err != nil { 42 log.Fatal(err.Error()) 43 } 44 } 45 } 46 47 return min, max 48 } 49 50 func randStringValue(column *column, n int) string { 51 if column.hist != nil { 52 if column.hist.avgLen == 0 { 53 column.hist.avgLen = column.hist.getAvgLen(n) 54 } 55 return column.hist.randString() 56 } 57 if len(column.set) > 0 { 58 idx := randInt(0, len(column.set)-1) 59 return column.set[idx] 60 } 61 return randString(randInt(1, n)) 62 } 63 64 func randInt64Value(column *column, min int64, max int64) int64 { 65 if column.hist != nil { 66 return column.hist.randInt() 67 } 68 if len(column.set) > 0 { 69 idx := randInt(0, len(column.set)-1) 70 data, err := strconv.ParseInt(column.set[idx], 10, 64) 71 if err != nil { 72 log.Warn("rand int64 failed", zap.Error(err)) 73 } 74 return data 75 } 76 77 min, max = intRangeValue(column, min, max) 78 return randInt64(min, max) 79 } 80 81 func nextInt64Value(column *column, min int64, max int64) int64 { 82 min, max = intRangeValue(column, min, max) 83 column.data.setInitInt64Value(min, max) 84 return column.data.nextInt64() 85 } 86 87 func intToDecimalString(intValue int64, decimal int) string { 88 data := fmt.Sprintf("%d", intValue) 89 90 // add leading zero 91 if len(data) < decimal { 92 data = strings.Repeat("0", decimal-len(data)) + data 93 } 94 95 dec := data[len(data)-decimal:] 96 if data = data[:len(data)-decimal]; data == "" { 97 data = "0" 98 } 99 if dec != "" { 100 data = data + "." + dec 101 } 102 return data 103 } 104 105 func genRowDatas(causet *causet, count int) ([]string, error) { 106 quantum := make([]string, 0, count) 107 for i := 0; i < count; i++ { 108 data, err := genRowData(causet) 109 if err != nil { 110 return nil, errors.Trace(err) 111 } 112 quantum = append(quantum, data) 113 } 114 115 return quantum, nil 116 } 117 118 func genRowData(causet *causet) (string, error) { 119 var values []byte 120 for _, column := range causet.columns { 121 data, err := genDeferredCausetData(causet, column) 122 if err != nil { 123 return "", errors.Trace(err) 124 } 125 values = append(values, []byte(data)...) 126 values = append(values, ',') 127 } 128 129 values = values[:len(values)-1] 130 allegrosql := fmt.Sprintf("insert into %s (%s) values (%s);", causet.name, causet.columnList, string(values)) 131 return allegrosql, nil 132 } 133 134 func genDeferredCausetData(causet *causet, column *column) (string, error) { 135 tp := column.tp 136 incremental := column.incremental 137 if incremental { 138 incremental = uint32(rand.Int31n(100))+1 <= column.data.probability 139 // If incremental, there is only one worker, so it is safe to directly access causet. 140 if !incremental && column.data.remains > 0 { 141 column.data.remains-- 142 } 143 } 144 if _, ok := causet.uniqIndices[column.name]; ok { 145 incremental = true 146 } 147 isUnsigned := allegrosql.HasUnsignedFlag(tp.Flag) 148 149 switch tp.Tp { 150 case allegrosql.TypeTiny: 151 var data int64 152 if incremental { 153 if isUnsigned { 154 data = nextInt64Value(column, 0, math.MaxUint8) 155 } else { 156 data = nextInt64Value(column, math.MinInt8, math.MaxInt8) 157 } 158 } else { 159 if isUnsigned { 160 data = randInt64Value(column, 0, math.MaxUint8) 161 } else { 162 data = randInt64Value(column, math.MinInt8, math.MaxInt8) 163 } 164 } 165 return strconv.FormatInt(data, 10), nil 166 case allegrosql.TypeShort: 167 var data int64 168 if incremental { 169 if isUnsigned { 170 data = nextInt64Value(column, 0, math.MaxUint16) 171 } else { 172 data = nextInt64Value(column, math.MinInt16, math.MaxInt16) 173 } 174 } else { 175 if isUnsigned { 176 data = randInt64Value(column, 0, math.MaxUint16) 177 } else { 178 data = randInt64Value(column, math.MinInt16, math.MaxInt16) 179 } 180 } 181 return strconv.FormatInt(data, 10), nil 182 case allegrosql.TypeLong: 183 var data int64 184 if incremental { 185 if isUnsigned { 186 data = nextInt64Value(column, 0, math.MaxUint32) 187 } else { 188 data = nextInt64Value(column, math.MinInt32, math.MaxInt32) 189 } 190 } else { 191 if isUnsigned { 192 data = randInt64Value(column, 0, math.MaxUint32) 193 } else { 194 data = randInt64Value(column, math.MinInt32, math.MaxInt32) 195 } 196 } 197 return strconv.FormatInt(data, 10), nil 198 case allegrosql.TypeLonglong: 199 var data int64 200 if incremental { 201 if isUnsigned { 202 data = nextInt64Value(column, 0, math.MaxInt64-1) 203 } else { 204 data = nextInt64Value(column, math.MinInt32, math.MaxInt32) 205 } 206 } else { 207 if isUnsigned { 208 data = randInt64Value(column, 0, math.MaxInt64-1) 209 } else { 210 data = randInt64Value(column, math.MinInt32, math.MaxInt32) 211 } 212 } 213 return strconv.FormatInt(data, 10), nil 214 case allegrosql.TypeVarchar, allegrosql.TypeString, allegrosql.TypeTinyBlob, allegrosql.TypeBlob, allegrosql.TypeMediumBlob, allegrosql.TypeLongBlob: 215 data := []byte{'\''} 216 if incremental { 217 data = append(data, []byte(column.data.nextString(tp.Flen))...) 218 } else { 219 data = append(data, []byte(randStringValue(column, tp.Flen))...) 220 } 221 222 data = append(data, '\'') 223 return string(data), nil 224 case allegrosql.TypeFloat, allegrosql.TypeDouble: 225 var data float64 226 if incremental { 227 if isUnsigned { 228 data = float64(nextInt64Value(column, 0, math.MaxInt64-1)) 229 } else { 230 data = float64(nextInt64Value(column, math.MinInt32, math.MaxInt32)) 231 } 232 } else { 233 if isUnsigned { 234 data = float64(randInt64Value(column, 0, math.MaxInt64-1)) 235 } else { 236 data = float64(randInt64Value(column, math.MinInt32, math.MaxInt32)) 237 } 238 } 239 return strconv.FormatFloat(data, 'f', -1, 64), nil 240 case allegrosql.TypeDate: 241 data := []byte{'\''} 242 if incremental { 243 data = append(data, []byte(column.data.nextDate())...) 244 } else { 245 data = append(data, []byte(randDate(column))...) 246 } 247 248 data = append(data, '\'') 249 return string(data), nil 250 case allegrosql.TypeDatetime, allegrosql.TypeTimestamp: 251 data := []byte{'\''} 252 if incremental { 253 data = append(data, []byte(column.data.nextTimestamp())...) 254 } else { 255 data = append(data, []byte(randTimestamp(column))...) 256 } 257 258 data = append(data, '\'') 259 return string(data), nil 260 case allegrosql.TypeDuration: 261 data := []byte{'\''} 262 if incremental { 263 data = append(data, []byte(column.data.nextTime())...) 264 } else { 265 data = append(data, []byte(randTime(column))...) 266 } 267 268 data = append(data, '\'') 269 return string(data), nil 270 case allegrosql.TypeYear: 271 data := []byte{'\''} 272 if incremental { 273 data = append(data, []byte(column.data.nextYear())...) 274 } else { 275 data = append(data, []byte(randYear(column))...) 276 } 277 278 data = append(data, '\'') 279 return string(data), nil 280 case allegrosql.TypeNewDecimal: 281 var limit = int64(math.Pow10(tp.Flen)) 282 var intVal int64 283 if limit < 0 { 284 limit = math.MaxInt64 285 } 286 if incremental { 287 if isUnsigned { 288 intVal = nextInt64Value(column, 0, limit-1) 289 } else { 290 intVal = nextInt64Value(column, (-limit+1)/2, (limit-1)/2) 291 } 292 } else { 293 if isUnsigned { 294 intVal = randInt64Value(column, 0, limit-1) 295 } else { 296 intVal = randInt64Value(column, (-limit+1)/2, (limit-1)/2) 297 } 298 } 299 return intToDecimalString(intVal, tp.Decimal), nil 300 default: 301 return "", errors.Errorf("unsupported column type - %v", column) 302 } 303 } 304 305 func execALLEGROSQL(EDB *allegrosql.EDB, allegrosql string) error { 306 if len(allegrosql) == 0 { 307 return nil 308 } 309 310 _, err := EDB.InterDirc(allegrosql) 311 if err != nil { 312 return errors.Trace(err) 313 } 314 315 return nil 316 } 317 318 func createDB(cfg DBConfig) (*allegrosql.EDB, error) { 319 dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", cfg.User, cfg.Password, cfg.Host, cfg.Port, cfg.Name) 320 EDB, err := allegrosql.Open("allegrosql", dbDSN) 321 if err != nil { 322 return nil, errors.Trace(err) 323 } 324 325 return EDB, nil 326 } 327 328 func closeDB(EDB *allegrosql.EDB) error { 329 return errors.Trace(EDB.Close()) 330 } 331 332 func createDBs(cfg DBConfig, count int) ([]*allegrosql.EDB, error) { 333 dbs := make([]*allegrosql.EDB, 0, count) 334 for i := 0; i < count; i++ { 335 EDB, err := createDB(cfg) 336 if err != nil { 337 return nil, errors.Trace(err) 338 } 339 340 dbs = append(dbs, EDB) 341 } 342 343 return dbs, nil 344 } 345 346 func closeDBs(dbs []*allegrosql.EDB) { 347 for _, EDB := range dbs { 348 err := closeDB(EDB) 349 if err != nil { 350 log.Error("close EDB failed", zap.Error(err)) 351 } 352 } 353 }