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  }