Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

planner: add more test cases for MVIndex #40853

Merged
merged 2 commits into from
Jan 30, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 122 additions & 0 deletions planner/core/indexmerge_path_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
package core_test

import (
"fmt"
"math/rand"
"strings"
"testing"

Expand Down Expand Up @@ -237,3 +239,123 @@ func TestEnforceMVIndex(t *testing.T) {
result.Check(testkit.Rows(output[i].Plan...))
}
}

func TestMVIndexInvisible(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")

tk.MustExec(`create table t(a int, j json, index kj((cast(j as signed array))))`)
tk.MustQuery(`explain format='brief' select /*+ use_index(t, kj) */ * from t where (1 member of (j))`).Check(testkit.Rows(
`Selection 8000.00 root json_memberof(cast(1, json BINARY), test.t.j)`,
`└─IndexMerge 10.00 root type: union`,
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:kj(cast(`j` as signed array)) range:[1,1], keep order:false, stats:pseudo",
` └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo`))

tk.MustExec(`ALTER TABLE t ALTER INDEX kj INVISIBLE`)
tk.MustQuery(`explain format='brief' select /*+ use_index(t, kj) */ * from t where (1 member of (j))`).Check(testkit.Rows(
"Selection 8000.00 root json_memberof(cast(1, json BINARY), test.t.j)",
"└─TableReader 10000.00 root data:TableFullScan",
" └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"))
tk.MustQuery(`explain format='brief' select /*+ use_index_merge(t, kj) */ * from t where (1 member of (j))`).Check(testkit.Rows(
"Selection 8000.00 root json_memberof(cast(1, json BINARY), test.t.j)",
"└─TableReader 10000.00 root data:TableFullScan",
" └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"))

tk.MustExec(`ALTER TABLE t ALTER INDEX kj VISIBLE`)
tk.MustQuery(`explain format='brief' select /*+ use_index(t, kj) */ * from t where (1 member of (j))`).Check(testkit.Rows(
`Selection 8000.00 root json_memberof(cast(1, json BINARY), test.t.j)`,
`└─IndexMerge 10.00 root type: union`,
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:kj(cast(`j` as signed array)) range:[1,1], keep order:false, stats:pseudo",
` └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo`))
}

func TestMVIndexRandom(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")

for _, testCase := range []struct {
indexType string
insertValOpts randMVIndexValOpts
queryValsOpts randMVIndexValOpts
}{
{"signed", randMVIndexValOpts{"signed", 0, 3}, randMVIndexValOpts{"signed", 0, 3}},
{"unsigned", randMVIndexValOpts{"unsigned", 0, 3}, randMVIndexValOpts{"unsigned", 0, 3}}, // unsigned-index + unsigned-values
{"char(3)", randMVIndexValOpts{"string", 3, 3}, randMVIndexValOpts{"string", 3, 3}},
{"char(3)", randMVIndexValOpts{"string", 3, 3}, randMVIndexValOpts{"string", 1, 3}},
//{"char(3)", randMVIndexValOpts{"string", 3, 3}, randMVIndexValOpts{"string", 5, 3}},
//{"date", randMVIndexValOpts{"date", 0, 3}, randMVIndexValOpts{"date", 0, 3}},
Comment on lines +287 to +288
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some new issues were found. I'll fix them in the next PR.

} {
tk.MustExec("drop table if exists t")
tk.MustExec(fmt.Sprintf(`create table t(a int, j json, index kj((cast(j as %v array))))`, testCase.indexType))

nRows := 20
rows := make([]string, 0, nRows)
for i := 0; i < nRows; i++ {
va, v1, v2 := rand.Intn(testCase.insertValOpts.distinct), randMVIndexValue(testCase.insertValOpts), randMVIndexValue(testCase.insertValOpts)
if testCase.indexType == "date" {
rows = append(rows, fmt.Sprintf(`(%v, json_array(cast(%v as date), cast(%v as date)))`, va, v1, v2))
} else {
rows = append(rows, fmt.Sprintf(`(%v, '[%v, %v]')`, va, v1, v2))
}
}
tk.MustExec(fmt.Sprintf("insert into t values %v", strings.Join(rows, ", ")))

nQueries := 20
for i := 0; i < nQueries; i++ {
conds := randMVIndexConds(rand.Intn(3)+1, testCase.queryValsOpts)
r1 := tk.MustQuery("select /*+ ignore_index(t, kj) */ * from t where " + conds).Sort()
tk.MustQuery("select /*+ use_index(t, kj) */ * from t where " + conds).Sort().Check(r1.Rows())
}
}
}

func randMVIndexConds(nConds int, valOpts randMVIndexValOpts) string {
var conds string
for i := 0; i < nConds; i++ {
if i > 0 {
if rand.Intn(5) < 1 { // OR
conds += " OR "
} else { // AND
conds += " AND "
}
}
cond := randMVIndexCond(rand.Intn(4), valOpts)
conds += cond
}
return conds
}

func randMVIndexCond(condType int, valOpts randMVIndexValOpts) string {
switch condType {
case 0: // member_of
return fmt.Sprintf(`(%v member of (j))`, randMVIndexValue(valOpts))
case 1: // json_contains
return fmt.Sprintf(`json_contains(j, '[%v, %v]')`, randMVIndexValue(valOpts), randMVIndexValue(valOpts))
case 2: // json_overlaps
return fmt.Sprintf(`json_overlaps(j, '[%v, %v]')`, randMVIndexValue(valOpts), randMVIndexValue(valOpts))
default: // others
return fmt.Sprintf(`a < %v`, rand.Intn(valOpts.distinct))
}
}

type randMVIndexValOpts struct {
valType string // INT, UNSIGNED, STR, DATE
maxStrLen int
distinct int
}

func randMVIndexValue(opts randMVIndexValOpts) string {
switch strings.ToLower(opts.valType) {
case "signed":
return fmt.Sprintf("%v", rand.Intn(opts.distinct)-(opts.distinct/2))
case "unsigned":
return fmt.Sprintf("%v", rand.Intn(opts.distinct))
case "string":
return fmt.Sprintf(`"%v"`, strings.Repeat(fmt.Sprintf("%v", rand.Intn(opts.distinct)), rand.Intn(opts.maxStrLen)+1))
case "date":
return fmt.Sprintf(`"2000-01-%v"`, rand.Intn(opts.distinct)+1)
}
return ""
}