Skip to content

Commit

Permalink
planner: add more test cases for MVIndex (#40853)
Browse files Browse the repository at this point in the history
ref #40191
  • Loading branch information
qw4990 authored Jan 30, 2023
1 parent 4ed4562 commit 86b058b
Showing 1 changed file with 122 additions and 0 deletions.
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}},
} {
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 ""
}

0 comments on commit 86b058b

Please sign in to comment.