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  }