github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/performance/benchmarks/helpers.go (about) 1 // Copyright 2019 Dolthub, 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 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package main 16 17 import ( 18 "fmt" 19 "log" 20 "math/rand" 21 "strconv" 22 "strings" 23 24 "github.com/dolthub/dolt/go/libraries/doltcore/schema/typeinfo" 25 26 "github.com/dolthub/dolt/go/store/types" 27 ) 28 29 type seedFunc func(col *SeedColumn, format string) string 30 31 // Container is used to correctly format strings enclosed in brackets 32 type Container struct { 33 c []string 34 } 35 36 // NewContainer creates a new Container 37 func NewContainer(format string) *Container { 38 c := make([]string, 3) 39 switch format { 40 case sqlExt: 41 c[0] = "(" 42 c[2] = ")" 43 case jsonExt: 44 c[0] = "{" 45 c[2] = "}" 46 default: 47 log.Fatalf("cannot create new container, unsupported format %s \n", format) 48 } 49 return &Container{c: c} 50 } 51 52 // InsertPayload returns the Container with the payload inserted, separated by the separator 53 func (sc *Container) InsertPayload(payload []string, separator string) string { 54 sc.c[1] = strings.Join(payload, separator) 55 return strings.Join(sc.c, "") 56 } 57 58 func getColValue(row []string, colIndex int, col *SeedColumn, sf seedFunc, format string) string { 59 switch col.GenType { 60 case increment: 61 return genNomsTypeValueIncrement(row, colIndex, col, format) 62 case random: 63 return getNomsTypeValueRandom(col, sf, format) 64 default: 65 log.Fatalf("cannot get column value, unsupported gen type %s \n", col.GenType) 66 } 67 return "" 68 } 69 70 func genNomsTypeValueIncrement(row []string, colIndex int, col *SeedColumn, format string) string { 71 switch col.Type { 72 case types.IntKind: 73 if len(row) > 0 { 74 old, err := strconv.Atoi(row[colIndex]) 75 if err != nil { 76 log.Fatalf(err.Error()) 77 } 78 return fmt.Sprintf("%d", old+1) 79 } 80 return "1" 81 default: 82 log.Fatalf("cannot generate incremental value, unsupported noms type %s \n", col.Type.String()) 83 } 84 return "" 85 } 86 87 func getNomsTypeValueRandom(col *SeedColumn, sf seedFunc, format string) string { 88 return sf(col, format) 89 } 90 91 // seedRandom is a seedFunc that returns variably random strings for each supported 92 // nomsKind type 93 func seedRandom(col *SeedColumn, format string) string { 94 switch col.Type { 95 case types.IntKind: 96 return fmt.Sprintf("%d", rand.Intn(1000)) 97 case types.StringKind: 98 return getRandomString(format) 99 default: 100 log.Fatalf("cannot generate random value, unsupported noms type %s \n", col.Type.String()) 101 } 102 return "" 103 } 104 105 func getRandomString(format string) string { 106 letters := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 107 b := make([]byte, rand.Intn(255)) 108 for i := range b { 109 b[i] = letters[rand.Int63()%int64(len(letters))] 110 } 111 112 switch format { 113 case sqlExt: 114 return fmt.Sprintf(`"%s"`, b) 115 default: 116 return string(b) 117 } 118 } 119 120 func getJSONRow(strs []string, cols []*SeedColumn) string { 121 if len(strs) != len(cols) { 122 log.Fatalf("values should be the length of columns. values: %+v, columns: %+v \n", strs, cols) 123 } 124 125 payload := make([]string, 0) 126 for i, col := range cols { 127 load := fmt.Sprintf("\"%s\":\"%s\"", col.Name, strs[i]) 128 payload = append(payload, load) 129 } 130 131 container := NewContainer(jsonExt) 132 return container.InsertPayload(payload, ",") 133 } 134 135 func getSQLRow(strs []string, cols []*SeedColumn, tableName string) string { 136 container := NewContainer(sqlExt) 137 sqlCols := make([]string, 0) 138 139 for _, col := range cols { 140 sqlCols = append(sqlCols, fmt.Sprintf("`%s`", col.Name)) 141 } 142 143 fieldNames := container.InsertPayload(sqlCols, ",") 144 values := container.InsertPayload(strs, ",") 145 146 return fmt.Sprintf("INSERT INTO `%s` %s VALUES %s;", tableName, fieldNames, values) 147 } 148 149 func getSQLHeader(cols []*SeedColumn, tableName, format string) string { 150 statement := make([]string, 0) 151 statement = append(statement, fmt.Sprintf("DROP TABLE IF EXISTS `%s`;\n", tableName)) 152 statement = append(statement, fmt.Sprintf("CREATE TABLE `%s` ", tableName)) 153 154 container := NewContainer(format) 155 schema := make([]string, 0) 156 pkDefs := make([]string, 0) 157 for i, col := range cols { 158 colStr := "`%s` %s" 159 160 // handle pk 161 if col.PrimaryKey { 162 pkDefs = append(pkDefs, fmt.Sprintf("PRIMARY KEY (`%s`)", col.Name)) 163 colStr = "`%s` %s NOT NULL" 164 } 165 166 // handle increments 167 if col.GenType == increment { 168 colStr = fmt.Sprintf("%s AUTO_INCREMENT", colStr) 169 } 170 171 // append tag 172 colStr = fmt.Sprintf("%s COMMENT 'tag:%d'", colStr, i) 173 174 // translate noms type 175 sqlType := typeinfo.FromKind(col.Type).ToSqlType().String() 176 177 schema = append(schema, fmt.Sprintf(colStr, col.Name, strings.ToUpper(sqlType))) 178 } 179 180 // add pk definitions to create table statement 181 for _, pkDef := range pkDefs { 182 schema = append(schema, pkDef) 183 } 184 185 // create and close create table statement 186 schemaStatement := container.InsertPayload(schema, ",\n") 187 statement = append(statement, schemaStatement+"; \n") 188 189 return strings.Join(statement, "") 190 }