From 541f8429ef09b6efda51b51179694b665ffd9d1d Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Wed, 7 Jun 2023 10:30:27 -0400 Subject: [PATCH 1/2] *rebased *added preselect affordable mutate, check and ddl functions from table conditions. --- pkg/jobs/functions_cases_test.go | 151 +++++++++++++++++++++++++++++++ pkg/jobs/gen_check_stmt.go | 74 +++++++++++++++ pkg/jobs/gen_ddl_stmt.go | 30 ++++-- pkg/jobs/gen_mutate_stmt.go | 68 ++++++++++---- pkg/jobs/jobs.go | 9 ++ pkg/typedef/functions_cases.go | 85 +++++++++++++++++ pkg/typedef/schema.go | 6 ++ pkg/typedef/table.go | 29 ++++-- pkg/typedef/typedef.go | 6 ++ pkg/utils/utils.go | 13 +++ 10 files changed, 436 insertions(+), 35 deletions(-) create mode 100644 pkg/jobs/functions_cases_test.go create mode 100644 pkg/typedef/functions_cases.go diff --git a/pkg/jobs/functions_cases_test.go b/pkg/jobs/functions_cases_test.go new file mode 100644 index 00000000..42841587 --- /dev/null +++ b/pkg/jobs/functions_cases_test.go @@ -0,0 +1,151 @@ +// Copyright 2019 ScyllaDB +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//nolint:thelper +package jobs_test + +import ( + "testing" + + "golang.org/x/exp/rand" + + "github.com/scylladb/gemini/pkg/generators" + "github.com/scylladb/gemini/pkg/jobs" + "github.com/scylladb/gemini/pkg/typedef" +) + +var genCheckfullCases = []int{ + jobs.GenSinglePartitionID, + jobs.GenSinglePartitionMvID, + jobs.GenMultiplePartitionID, + jobs.GenMultiplePartitionMvID, + jobs.GenClusteringRangeID, + jobs.GenClusteringRangeMvID, + jobs.GenMultiplePartitionClusteringRangeID, + jobs.GenMultiplePartitionClusteringRangeMvID, + jobs.GenSingleIndexQueryID, +} + +var genCheckNoIndex = []int{ + jobs.GenSinglePartitionID, + jobs.GenSinglePartitionMvID, + jobs.GenMultiplePartitionID, + jobs.GenMultiplePartitionMvID, + jobs.GenClusteringRangeID, + jobs.GenClusteringRangeMvID, + jobs.GenMultiplePartitionClusteringRangeID, + jobs.GenMultiplePartitionClusteringRangeMvID, +} + +var genCheckNoMV = []int{ + jobs.GenSinglePartitionID, + jobs.GenMultiplePartitionID, + jobs.GenClusteringRangeID, + jobs.GenMultiplePartitionClusteringRangeID, + jobs.GenSingleIndexQueryID, +} + +var genCheckNoClustering = []int{ + jobs.GenSinglePartitionID, + jobs.GenSinglePartitionMvID, + jobs.GenMultiplePartitionID, + jobs.GenMultiplePartitionMvID, + jobs.GenSingleIndexQueryID, +} + +var genCheckMin = []int{ + jobs.GenSinglePartitionID, + jobs.GenMultiplePartitionID, +} + +type comparer struct { + expected []int + received typedef.CasesInfo +} + +func TestGetFuncCases(t *testing.T) { + tableFull := getTestTable() + + tableNoIndexes := getTestTable() + tableNoIndexes.Indexes = nil + + tableNoMV := getTestTable() + tableNoMV.MaterializedViews = nil + + tableNoClustering := getTestTable() + tableNoClustering.ClusteringKeys = nil + + tableMin := getTestTable() + tableMin.Indexes = nil + tableMin.MaterializedViews = nil + tableMin.ClusteringKeys = nil + + genCheckList := map[string]comparer{ + "genCheck_fullCases": {received: typedef.UpdateFuncCases(&tableFull, jobs.GenCheckStmtConditions, jobs.GenCheckStmtRatios), expected: genCheckfullCases}, + "genCheck_NoIndex": {received: typedef.UpdateFuncCases(&tableNoIndexes, jobs.GenCheckStmtConditions, jobs.GenCheckStmtRatios), expected: genCheckNoIndex}, + "genCheck_NoMV": {received: typedef.UpdateFuncCases(&tableNoMV, jobs.GenCheckStmtConditions, jobs.GenCheckStmtRatios), expected: genCheckNoMV}, + "genCheck_NoClustering": {received: typedef.UpdateFuncCases(&tableNoClustering, jobs.GenCheckStmtConditions, jobs.GenCheckStmtRatios), expected: genCheckNoClustering}, + "genCheck_Min": {received: typedef.UpdateFuncCases(&tableMin, jobs.GenCheckStmtConditions, jobs.GenCheckStmtRatios), expected: genCheckMin}, + } + compareResults(t, genCheckList) + + funcsList := typedef.UpdateFuncCases(&tableFull, jobs.GenCheckStmtConditions, jobs.GenCheckStmtRatios) + idx := funcsList.RandomCase(rand.New(rand.NewSource(123))) + _ = idx +} + +func compareResults(t *testing.T, results map[string]comparer) { + for caseName := range results { + checkPresenceCases(t, caseName, results[caseName].received, results[caseName].expected...) + } +} + +func checkPresenceCases(t *testing.T, caseName string, funcs typedef.CasesInfo, expected ...int) { + received := make([]int, 0, len(expected)) + for i := range expected { + for j := range funcs.List { + if expected[i] == funcs.List[j].ID { + received = append(received, expected[i]) + break + } + } + } + if len(received) != len(expected) { + t.Errorf("wrong function cases for case:%s \nexpected:%v \nreceived:%v ", caseName, expected, received) + } +} + +func getTestTable() typedef.Table { + col := typedef.ColumnDef{ + Name: "col_0", + Type: typedef.TYPE_INT, + } + cols := typedef.Columns{&col, &col} + index := typedef.IndexDef{ + Name: "id_1", + Column: cols[0], + } + return typedef.Table{ + Name: "tb1", + PartitionKeys: cols, + ClusteringKeys: cols, + Columns: cols, + Indexes: typedef.Indexes{index, index}, + MaterializedViews: generators.CreateMaterializedViews(cols, "mv1", cols, cols), + KnownIssues: map[string]bool{ + typedef.KnownIssuesJSONWithTuples: true, + }, + TableOptions: nil, + } +} diff --git a/pkg/jobs/gen_check_stmt.go b/pkg/jobs/gen_check_stmt.go index 41565ced..9e575b79 100644 --- a/pkg/jobs/gen_check_stmt.go +++ b/pkg/jobs/gen_check_stmt.go @@ -25,6 +25,80 @@ import ( "github.com/scylladb/gemini/pkg/utils" ) +const ( + GenSinglePartitionID = iota + GenSinglePartitionMvID + GenMultiplePartitionID + GenMultiplePartitionMvID + GenClusteringRangeID + GenClusteringRangeMvID + GenMultiplePartitionClusteringRangeID + GenMultiplePartitionClusteringRangeMvID + GenSingleIndexQueryID +) + +var GenCheckStmtConditions = typedef.CasesConditions{ + GenSinglePartitionID: func(table *typedef.Table) bool { return true }, + GenSinglePartitionMvID: func(table *typedef.Table) bool { return table.HasMV() }, + GenMultiplePartitionID: func(table *typedef.Table) bool { return true }, + GenMultiplePartitionMvID: func(table *typedef.Table) bool { return table.HasMV() }, + GenClusteringRangeID: func(table *typedef.Table) bool { return table.HasClusteringKeys() }, + GenClusteringRangeMvID: func(table *typedef.Table) bool { return table.HasClusteringKeys() && table.HasMV() }, + GenMultiplePartitionClusteringRangeID: func(table *typedef.Table) bool { return table.HasClusteringKeys() }, + GenMultiplePartitionClusteringRangeMvID: func(table *typedef.Table) bool { return table.HasClusteringKeys() && table.HasMV() }, + GenSingleIndexQueryID: func(table *typedef.Table) bool { return table.HasIndexes() }, +} + +var GenCheckStmtRatios = typedef.CasesRatios{ + GenSinglePartitionID: 20, + GenSinglePartitionMvID: 20, + GenMultiplePartitionID: 20, + GenMultiplePartitionMvID: 20, + GenClusteringRangeID: 20, + GenClusteringRangeMvID: 20, + GenMultiplePartitionClusteringRangeID: 20, + GenMultiplePartitionClusteringRangeMvID: 20, + GenSingleIndexQueryID: 1, +} + +func GenCheckStmtNew(s *typedef.Schema, table *typedef.Table, g generators.GeneratorInterface, rnd *rand.Rand, p *typedef.PartitionRangeConfig) *typedef.Stmt { + switch table.AvailableFuncs.Check.RandomCase(rnd) { + case GenSinglePartitionID: + return genSinglePartitionQuery(s, table, g) + case GenMultiplePartitionID: + numQueryPKs := utils.RandIntLimited(rnd, 1, table.PartitionKeys.Len()) + return genMultiplePartitionQuery(s, table, g, numQueryPKs) + case GenClusteringRangeID: + maxClusteringRels := utils.RandInt2(rnd, 1, table.ClusteringKeys.Len()) + return genClusteringRangeQuery(s, table, g, rnd, p, maxClusteringRels) + case GenMultiplePartitionClusteringRangeID: + numQueryPKs := utils.RandIntLimited(rnd, 1, table.PartitionKeys.Len()) + maxClusteringRels := utils.RandInt2(rnd, 1, table.ClusteringKeys.Len()) + return genMultiplePartitionClusteringRangeQuery(s, table, g, rnd, p, numQueryPKs, maxClusteringRels) + case GenSinglePartitionMvID: + mvNum := utils.RandInt2(rnd, 0, table.MaterializedViews.Len()) + return genSinglePartitionQueryMv(s, table, g, rnd, p, mvNum) + case GenMultiplePartitionMvID: + mvNum := utils.RandInt2(rnd, 0, table.MaterializedViews.Len()) + numQueryPKs := utils.RandIntLimited(rnd, 1, table.PartitionKeys.Len()) + return genMultiplePartitionQueryMv(s, table, g, rnd, p, mvNum, numQueryPKs) + case GenClusteringRangeMvID: + mvNum := utils.RandInt2(rnd, 0, table.MaterializedViews.Len()) + maxClusteringRels := utils.RandInt2(rnd, 1, table.ClusteringKeys.Len()) + return genClusteringRangeQueryMv(s, table, g, rnd, p, mvNum, maxClusteringRels) + case GenMultiplePartitionClusteringRangeMvID: + mvNum := utils.RandInt2(rnd, 0, table.MaterializedViews.Len()) + numQueryPKs := utils.RandIntLimited(rnd, 1, table.PartitionKeys.Len()) + maxClusteringRels := utils.RandInt2(rnd, 1, table.ClusteringKeys.Len()) + return genMultiplePartitionClusteringRangeQueryMv(s, table, g, rnd, p, mvNum, numQueryPKs, maxClusteringRels) + case GenSingleIndexQueryID: + idxCount := utils.RandInt2(rnd, 0, table.Indexes.Len()) + return genSingleIndexQuery(s, table, g, rnd, p, idxCount) + + } + return nil +} + func GenCheckStmt( s *typedef.Schema, table *typedef.Table, diff --git a/pkg/jobs/gen_ddl_stmt.go b/pkg/jobs/gen_ddl_stmt.go index c6d586d2..8a2a0cbe 100644 --- a/pkg/jobs/gen_ddl_stmt.go +++ b/pkg/jobs/gen_ddl_stmt.go @@ -26,21 +26,31 @@ import ( "github.com/scylladb/gemini/pkg/typedef" ) +const ( + GenAddColumnStmtID = iota + GenDropColumnStmtID +) + +var GenDdlStmtConditions = typedef.CasesConditions{ + GenAddColumnStmtID: func(table *typedef.Table) bool { return true }, + GenDropColumnStmtID: func(table *typedef.Table) bool { return len(table.Columns) > 1 }, +} + +var GenDdlStmtRatios = typedef.CasesRatios{ + GenAddColumnStmtID: 3, + GenDropColumnStmtID: 1, +} + func GenDDLStmt(s *typedef.Schema, t *typedef.Table, r *rand.Rand, _ *typedef.PartitionRangeConfig, sc *typedef.SchemaConfig) (*typedef.Stmts, error) { - maxVariant := 1 - if len(t.Columns) > 0 { - maxVariant = 2 - } - switch n := r.Intn(maxVariant + 2); n { - // case 0: // Alter column not supported in Cassandra from 3.0.11 - // return t.alterColumn(s.Keyspace.Name) - case 2: + switch t.AvailableFuncs.DDL.RandomCase(r) { + case GenDropColumnStmtID: colNum := r.Intn(len(t.Columns)) return genDropColumnStmt(t, s.Keyspace.Name, colNum) - default: + case GenAddColumnStmtID: column := typedef.ColumnDef{Name: generators.GenColumnName("col", len(t.Columns)+1), Type: generators.GenColumnType(len(t.Columns)+1, sc)} return genAddColumnStmt(t, s.Keyspace.Name, &column) } + return nil, nil } func appendValue(columnType typedef.Type, r *rand.Rand, p *typedef.PartitionRangeConfig, values []interface{}) []interface{} { @@ -76,6 +86,7 @@ func genAddColumnStmt(t *typedef.Table, keyspace string, column *typedef.ColumnD List: stmts, PostStmtHook: func() { t.Columns = append(t.Columns, column) + t.AvailableFuncs = UpdateAllCases(t) t.ResetQueryCache() }, }, nil @@ -128,6 +139,7 @@ func genDropColumnStmt(t *typedef.Table, keyspace string, colNum int) (*typedef. List: stmts, PostStmtHook: func() { t.Columns = t.Columns.Remove(colNum) + t.AvailableFuncs = UpdateAllCases(t) t.ResetQueryCache() }, }, nil diff --git a/pkg/jobs/gen_mutate_stmt.go b/pkg/jobs/gen_mutate_stmt.go index 07283c1e..d83f61f7 100644 --- a/pkg/jobs/gen_mutate_stmt.go +++ b/pkg/jobs/gen_mutate_stmt.go @@ -26,7 +26,37 @@ import ( "github.com/scylladb/gemini/pkg/typedef" ) -func GenMutateStmt(s *typedef.Schema, t *typedef.Table, g generators.GeneratorInterface, r *rand.Rand, p *typedef.PartitionRangeConfig, deletes bool) (*typedef.Stmt, error) { +const ( + GenInsertStmtID = iota + GenUpdateStmtID + GenInsertJSONStmtID + GenDeleteRowsID +) + +var GenMutateStmtConditions = typedef.CasesConditions{ + GenUpdateStmtID: func(table *typedef.Table) bool { return true }, + GenInsertStmtID: func(table *typedef.Table) bool { return !table.IsCounterTable() }, + GenInsertJSONStmtID: func(table *typedef.Table) bool { + return !table.KnownIssues[typedef.KnownIssuesJSONWithTuples] && !table.IsCounterTable() + }, + GenDeleteRowsID: func(table *typedef.Table) bool { return true }, +} + +var GenMutateStmtRatios = typedef.CasesRatios{ + GenInsertStmtID: 190, + GenUpdateStmtID: 190, + GenInsertJSONStmtID: 120, + GenDeleteRowsID: 1, +} + +func GenMutateStmt( + s *typedef.Schema, + t *typedef.Table, + g generators.GeneratorInterface, + r *rand.Rand, + p *typedef.PartitionRangeConfig, + deletes bool, +) (*typedef.Stmt, error) { t.RLock() defer t.RUnlock() @@ -34,28 +64,30 @@ func GenMutateStmt(s *typedef.Schema, t *typedef.Table, g generators.GeneratorIn if valuesWithToken == nil { return nil, nil } - useLWT := false - if p.UseLWT && r.Uint32()%10 == 0 { - useLWT = true - } if !deletes { - return genInsertOrUpdateStmt(s, t, valuesWithToken, r, p, useLWT) + return genInsertOrUpdateStmt(s, t, valuesWithToken, r, p, false) } - switch n := rand.Intn(1000); n { - case 10, 100: - return genDeleteRows(s, t, valuesWithToken, r, p) - default: - switch rand.Intn(2) { - case 0: - if t.KnownIssues[typedef.KnownIssuesJSONWithTuples] { - return genInsertOrUpdateStmt(s, t, valuesWithToken, r, p, useLWT) - } - return genInsertJSONStmt(s, t, valuesWithToken, r, p) - default: - return genInsertOrUpdateStmt(s, t, valuesWithToken, r, p, useLWT) + + if t.IsCounterTable() { // TODO: for counter tables scylla supports update and delete rows. Need to inspect gemini on deleting rows for counter tables and remove this restriction. + return genUpdateStmt(s, t, valuesWithToken, r, p) + } + + switch t.AvailableFuncs.Mutate.RandomCase(r) { + case GenInsertStmtID: + useLWT := false + if p.UseLWT && r.Uint32()%10 == 0 { + useLWT = true } + return genInsertStmt(s, t, valuesWithToken, r, p, useLWT) + case GenInsertJSONStmtID: + return genInsertJSONStmt(s, t, valuesWithToken, r, p) + case GenDeleteRowsID: + return genDeleteRows(s, t, valuesWithToken, r, p) + case GenUpdateStmtID: + return genUpdateStmt(s, t, valuesWithToken, r, p) } + return nil, nil } func genInsertOrUpdateStmt( diff --git a/pkg/jobs/jobs.go b/pkg/jobs/jobs.go index 6a341f73..b20b1194 100644 --- a/pkg/jobs/jobs.go +++ b/pkg/jobs/jobs.go @@ -135,6 +135,7 @@ func (l List) Run( } logger.Info("start jobs") for j := range schema.Tables { + schema.Tables[j].AvailableFuncs = UpdateAllCases(schema.Tables[j]) gen := generators[j] table := schema.Tables[j] for i := 0; i < int(l.workers); i++ { @@ -479,3 +480,11 @@ func unWrapErr(err error) error { } return err } + +func UpdateAllCases(table *typedef.Table) typedef.Functions { + return typedef.Functions{ + Check: typedef.UpdateFuncCases(table, GenCheckStmtConditions, GenCheckStmtRatios), + Mutate: typedef.UpdateFuncCases(table, GenMutateStmtConditions, GenMutateStmtRatios), + DDL: typedef.UpdateFuncCases(table, GenDdlStmtConditions, GenDdlStmtRatios), + } +} diff --git a/pkg/typedef/functions_cases.go b/pkg/typedef/functions_cases.go new file mode 100644 index 00000000..30887904 --- /dev/null +++ b/pkg/typedef/functions_cases.go @@ -0,0 +1,85 @@ +// Copyright 2019 ScyllaDB +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package typedef + +import ( + "sort" + + "golang.org/x/exp/rand" +) + +type ( + Functions struct { + Check CasesInfo + Mutate CasesInfo + DDL CasesInfo + } + CasesInfo struct { + List Cases + SumCasesRatio int + } + Cases []Case + Case struct { + ID int + From int + To int + } + + // CasesConditions contains functions that defines the conditions under which case functions can be executed + // + // If function return true, it means that case function can be executed for this table + CasesConditions map[int]func(table *Table) bool + + // CasesRatios contains ratios that defines case function execution ratio in relation to other case functions + // + // If function #1 have ratio 1 and function #2 have ratio 9 sumRatio will be 10 + // + // It means that from 10 executions function #1 will be executed 1 times and function #2 - 9 times + CasesRatios map[int]int +) + +func UpdateFuncCases(table *Table, conditions CasesConditions, ratios CasesRatios) CasesInfo { + cases := make(Cases, 0, len(conditions)) + for CaseNum, condition := range conditions { + if condition(table) { + cases = append(cases, Case{ + ID: CaseNum, + }) + } + } + sort.Slice(cases, func(i, j int) bool { + if ratios[cases[i].ID] == ratios[cases[j].ID] { + return cases[i].ID < cases[j].ID + } + return ratios[cases[i].ID] > ratios[cases[j].ID] + }) + sumRatio := 0 + for idx := range cases { + cases[idx].From = sumRatio + sumRatio += ratios[cases[idx].ID] + cases[idx].To = sumRatio + } + return CasesInfo{List: cases, SumCasesRatio: sumRatio} +} + +func (c CasesInfo) RandomCase(rnd *rand.Rand) int { + spin := rnd.Intn(c.SumCasesRatio - 1) + for idx := range c.List { + if spin >= c.List[idx].From && spin < c.List[idx].To { + return c.List[idx].ID + } + } + return 0 +} diff --git a/pkg/typedef/schema.go b/pkg/typedef/schema.go index d36dfe96..4f6f9f8e 100644 --- a/pkg/typedef/schema.go +++ b/pkg/typedef/schema.go @@ -14,6 +14,8 @@ package typedef +type MaterializedViews []MaterializedView + type MaterializedView struct { NonPrimaryKey *ColumnDef Name string `json:"name"` @@ -37,3 +39,7 @@ func (m *MaterializedView) PartitionKeysLenValues() int { } return m.partitionKeysLenValues } + +func (m MaterializedViews) Len() int { + return len(m) +} diff --git a/pkg/typedef/table.go b/pkg/typedef/table.go index 29a9aa25..16b53fb6 100644 --- a/pkg/typedef/table.go +++ b/pkg/typedef/table.go @@ -29,14 +29,15 @@ type KnownIssues map[string]bool type Table struct { queryCache QueryCache schema *Schema - Name string `json:"name"` - PartitionKeys Columns `json:"partition_keys"` - ClusteringKeys Columns `json:"clustering_keys"` - Columns Columns `json:"columns"` - Indexes []IndexDef `json:"indexes,omitempty"` - MaterializedViews []MaterializedView `json:"materialized_views,omitempty"` - KnownIssues KnownIssues `json:"known_issues"` - TableOptions []string `json:"table_options,omitempty"` + Name string `json:"name"` + PartitionKeys Columns `json:"partition_keys"` + ClusteringKeys Columns `json:"clustering_keys"` + Columns Columns `json:"columns"` + Indexes Indexes `json:"indexes,omitempty"` + MaterializedViews MaterializedViews `json:"materialized_views,omitempty"` + KnownIssues KnownIssues `json:"known_issues"` + TableOptions []string `json:"table_options,omitempty"` + AvailableFuncs Functions partitionKeysLenValues int // mu protects the table during schema changes @@ -88,3 +89,15 @@ func (t *Table) Init(s *Schema, c QueryCache) { t.queryCache = c t.queryCache.BindToTable(t) } + +func (t *Table) HasClusteringKeys() bool { + return len(t.ClusteringKeys) != 0 +} + +func (t *Table) HasMV() bool { + return len(t.MaterializedViews) != 0 +} + +func (t *Table) HasIndexes() bool { + return len(t.Indexes) != 0 +} diff --git a/pkg/typedef/typedef.go b/pkg/typedef/typedef.go index bdbda6ab..8a2b3bc5 100644 --- a/pkg/typedef/typedef.go +++ b/pkg/typedef/typedef.go @@ -33,6 +33,8 @@ type ( Name string `json:"name"` } + Indexes []IndexDef + IndexDef struct { Column *ColumnDef Name string `json:"name"` @@ -134,3 +136,7 @@ const ( CacheDelete CacheArrayLen ) + +func (i Indexes) Len() int { + return len(i) +} diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 463003ff..d360f17a 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -17,6 +17,7 @@ package utils import ( "encoding/hex" "fmt" + "math" "strconv" "strings" "time" @@ -97,3 +98,15 @@ func UUIDFromTime(rnd *rand.Rand) string { } return gocql.UUIDFromTime(RandTime(rnd)).String() } + +func RandIntLimited(rnd *rand.Rand, min, max int) int { + out := rnd.Intn(max) + if out < min { + out = min + } + multiplier := int(math.Pow(float64(out), float64(max))) + if multiplier > 100 { + out = min + } + return out +} From 889544acb215be95d018f6838b55bea32d341e52 Mon Sep 17 00:00:00 2001 From: illia-li Date: Sun, 11 Jun 2023 13:52:29 -0400 Subject: [PATCH 2/2] *some fixes --- pkg/jobs/gen_check_stmt.go | 98 +++---------------------------------- pkg/jobs/gen_ddl_stmt.go | 4 -- pkg/jobs/gen_mutate_stmt.go | 8 +-- 3 files changed, 12 insertions(+), 98 deletions(-) diff --git a/pkg/jobs/gen_check_stmt.go b/pkg/jobs/gen_check_stmt.go index 9e575b79..fbfbea77 100644 --- a/pkg/jobs/gen_check_stmt.go +++ b/pkg/jobs/gen_check_stmt.go @@ -15,8 +15,6 @@ package jobs import ( - "math" - "github.com/scylladb/gocqlx/v2/qb" "golang.org/x/exp/rand" @@ -61,7 +59,13 @@ var GenCheckStmtRatios = typedef.CasesRatios{ GenSingleIndexQueryID: 1, } -func GenCheckStmtNew(s *typedef.Schema, table *typedef.Table, g generators.GeneratorInterface, rnd *rand.Rand, p *typedef.PartitionRangeConfig) *typedef.Stmt { +func GenCheckStmt( + s *typedef.Schema, + table *typedef.Table, + g generators.GeneratorInterface, + rnd *rand.Rand, + p *typedef.PartitionRangeConfig, +) *typedef.Stmt { switch table.AvailableFuncs.Check.RandomCase(rnd) { case GenSinglePartitionID: return genSinglePartitionQuery(s, table, g) @@ -99,92 +103,6 @@ func GenCheckStmtNew(s *typedef.Schema, table *typedef.Table, g generators.Gener return nil } -func GenCheckStmt( - s *typedef.Schema, - table *typedef.Table, - g generators.GeneratorInterface, - rnd *rand.Rand, - p *typedef.PartitionRangeConfig, -) *typedef.Stmt { - n := 0 - mvNum := -1 - maxClusteringRels := 0 - numQueryPKs := 0 - if len(table.MaterializedViews) > 0 && rnd.Int()%2 == 0 { - mvNum = utils.RandInt2(rnd, 0, len(table.MaterializedViews)) - } - - switch mvNum { - case -1: - if len(table.Indexes) > 0 { - n = rnd.Intn(5) - } else { - n = rnd.Intn(4) - } - switch n { - case 0: - return genSinglePartitionQuery(s, table, g) - case 1: - numQueryPKs = utils.RandInt2(rnd, 1, table.PartitionKeys.Len()) - multiplier := int(math.Pow(float64(numQueryPKs), float64(table.PartitionKeys.Len()))) - if multiplier > 100 { - numQueryPKs = 1 - } - return genMultiplePartitionQuery(s, table, g, numQueryPKs) - case 2: - maxClusteringRels = utils.RandInt2(rnd, 0, table.ClusteringKeys.Len()) - return genClusteringRangeQuery(s, table, g, rnd, p, maxClusteringRels) - case 3: - numQueryPKs = utils.RandInt2(rnd, 1, table.PartitionKeys.Len()) - multiplier := int(math.Pow(float64(numQueryPKs), float64(table.PartitionKeys.Len()))) - if multiplier > 100 { - numQueryPKs = 1 - } - maxClusteringRels = utils.RandInt2(rnd, 0, table.ClusteringKeys.Len()) - return genMultiplePartitionClusteringRangeQuery(s, table, g, rnd, p, numQueryPKs, maxClusteringRels) - case 4: - // Reducing the probability to hit these since they often take a long time to run - switch rnd.Intn(5) { - case 0: - idxCount := utils.RandInt2(rnd, 1, len(table.Indexes)) - return genSingleIndexQuery(s, table, g, rnd, p, idxCount) - default: - return genSinglePartitionQuery(s, table, g) - } - } - default: - n = rnd.Intn(4) - switch n { - case 0: - return genSinglePartitionQueryMv(s, table, g, rnd, p, mvNum) - case 1: - lenPartitionKeys := table.MaterializedViews[mvNum].PartitionKeys.Len() - numQueryPKs = utils.RandInt2(rnd, 1, lenPartitionKeys) - multiplier := int(math.Pow(float64(numQueryPKs), float64(lenPartitionKeys))) - if multiplier > 100 { - numQueryPKs = 1 - } - return genMultiplePartitionQueryMv(s, table, g, rnd, p, mvNum, numQueryPKs) - case 2: - lenClusteringKeys := table.MaterializedViews[mvNum].ClusteringKeys.Len() - maxClusteringRels = utils.RandInt2(rnd, 0, lenClusteringKeys) - return genClusteringRangeQueryMv(s, table, g, rnd, p, mvNum, maxClusteringRels) - case 3: - lenPartitionKeys := table.MaterializedViews[mvNum].PartitionKeys.Len() - numQueryPKs = utils.RandInt2(rnd, 1, lenPartitionKeys) - multiplier := int(math.Pow(float64(numQueryPKs), float64(lenPartitionKeys))) - if multiplier > 100 { - numQueryPKs = 1 - } - lenClusteringKeys := table.MaterializedViews[mvNum].ClusteringKeys.Len() - maxClusteringRels = utils.RandInt2(rnd, 0, lenClusteringKeys) - return genMultiplePartitionClusteringRangeQueryMv(s, table, g, rnd, p, mvNum, numQueryPKs, maxClusteringRels) - } - } - - return nil -} - func genSinglePartitionQuery( s *typedef.Schema, t *typedef.Table, @@ -314,7 +232,7 @@ func genMultiplePartitionQueryMv( return nil } if i == 0 { - values = appendValue(pk.Type, r, p, values) + values = append(values, pk.Type.GenValue(r, p)...) typs = append(typs, pk.Type) } else { values = append(values, vs.Value[i-1]) diff --git a/pkg/jobs/gen_ddl_stmt.go b/pkg/jobs/gen_ddl_stmt.go index 8a2a0cbe..cb0adb9c 100644 --- a/pkg/jobs/gen_ddl_stmt.go +++ b/pkg/jobs/gen_ddl_stmt.go @@ -53,10 +53,6 @@ func GenDDLStmt(s *typedef.Schema, t *typedef.Table, r *rand.Rand, _ *typedef.Pa return nil, nil } -func appendValue(columnType typedef.Type, r *rand.Rand, p *typedef.PartitionRangeConfig, values []interface{}) []interface{} { - return append(values, columnType.GenValue(r, p)...) -} - func genAddColumnStmt(t *typedef.Table, keyspace string, column *typedef.ColumnDef) (*typedef.Stmts, error) { var stmts []*typedef.Stmt if c, ok := column.Type.(*typedef.UDTType); ok { diff --git a/pkg/jobs/gen_mutate_stmt.go b/pkg/jobs/gen_mutate_stmt.go index d83f61f7..88cfd348 100644 --- a/pkg/jobs/gen_mutate_stmt.go +++ b/pkg/jobs/gen_mutate_stmt.go @@ -109,11 +109,11 @@ func genUpdateStmt(_ *typedef.Schema, t *typedef.Table, valuesWithToken *typedef nonCounters := t.Columns.NonCounters() values := make(typedef.Values, 0, t.PartitionKeys.LenValues()+t.ClusteringKeys.LenValues()+nonCounters.LenValues()) for _, cdef := range nonCounters { - values = appendValue(cdef.Type, r, p, values) + values = append(values, cdef.Type.GenValue(r, p)...) } values = values.CopyFrom(valuesWithToken.Value) for _, ck := range t.ClusteringKeys { - values = appendValue(ck.Type, r, p, values) + values = append(values, ck.Type.GenValue(r, p)...) } return &typedef.Stmt{ StmtCache: stmtCache, @@ -218,8 +218,8 @@ func genDeleteRows(_ *typedef.Schema, t *typedef.Table, valuesWithToken *typedef values := valuesWithToken.Value.Copy() if len(t.ClusteringKeys) > 0 { ck := t.ClusteringKeys[0] - values = appendValue(ck.Type, r, p, values) - values = appendValue(ck.Type, r, p, values) + values = append(values, ck.Type.GenValue(r, p)...) + values = append(values, ck.Type.GenValue(r, p)...) } return &typedef.Stmt{ StmtCache: stmtCache,