Skip to content

Commit

Permalink
planner: not allow the optimizer to use json_contains(j, '[]') as a…
Browse files Browse the repository at this point in the history
…ccess conditions on MVIndex (pingcap#41013)

ref pingcap#40191
  • Loading branch information
qw4990 authored and ghazalfamilyusa committed Feb 6, 2023
1 parent 84d3f20 commit 0a1d0c5
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 4 deletions.
4 changes: 2 additions & 2 deletions planner/core/indexmerge_path.go
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,7 @@ func (ds *DataSource) buildPartialPaths4MVIndex(accessFilters []expression.Expre
case ast.JSONContains: // (json_contains(a->'$.zip', '[1, 2, 3]')
isIntersection = true
virColVals, ok = jsonArrayExpr2Exprs(ds.ctx, sf.GetArgs()[1], jsonType)
if !ok {
if !ok || len(virColVals) == 0 { // json_contains(JSON, '[]') is TRUE
return nil, false, false, nil
}
case ast.JSONOverlaps: // (json_overlaps(a->'$.zip', '[1, 2, 3]')
Expand All @@ -682,7 +682,7 @@ func (ds *DataSource) buildPartialPaths4MVIndex(accessFilters []expression.Expre
}
var ok bool
virColVals, ok = jsonArrayExpr2Exprs(ds.ctx, sf.GetArgs()[1-jsonPathIdx], jsonType)
if !ok {
if !ok || len(virColVals) == 0 { // forbid empty array for safety
return nil, false, false, nil
}
default:
Expand Down
38 changes: 36 additions & 2 deletions planner/core/indexmerge_path_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,31 @@ func TestMVIndexFullScan(t *testing.T) {
tk.MustGetErrMsg(`select /*+ use_index(t, kj) */ count(*) from t`, "[planner:1815]Internal : Can't find a proper physical plan for this query")
}

func TestMVIndexEmptyArray(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec(`create table t(j json, index kj((cast(j as signed array))))`)
tk.MustExec(`insert into t values ('[1]')`)
tk.MustExec(`insert into t values ('[1, 2]')`)
tk.MustExec(`insert into t values ('[]')`)
tk.MustExec(`insert into t values (NULL)`)

for _, cond := range []string{
"json_contains(j, '[]')",
"json_contains(j, '[1]')",
"json_contains(j, '[1, 2]')",
"json_contains(j, '[1, 10]')",
"json_overlaps(j, '[]')",
"json_overlaps(j, '[1]')",
"json_overlaps(j, '[1, 2]')",
"json_overlaps(j, '[1, 10]')",
} {
tk.MustQuery(fmt.Sprintf("select /*+ use_index_merge(t) */ * from t where %v", cond)).Sort().Check(
tk.MustQuery(fmt.Sprintf("select /*+ ignore_index(t, kj) */ * from t where %v", cond)).Sort().Rows())
}
}

func TestMVIndexRandom(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
Expand Down Expand Up @@ -364,14 +389,23 @@ func randMVIndexCond(condType int, valOpts randMVIndexValOpts) string {
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))
return fmt.Sprintf(`json_contains(j, '%v')`, randArray(valOpts))
case 2: // json_overlaps
return fmt.Sprintf(`json_overlaps(j, '[%v, %v]')`, randMVIndexValue(valOpts), randMVIndexValue(valOpts))
return fmt.Sprintf(`json_overlaps(j, '%v')`, randArray(valOpts))
default: // others
return fmt.Sprintf(`a < %v`, rand.Intn(valOpts.distinct))
}
}

func randArray(opts randMVIndexValOpts) string {
n := rand.Intn(5) // n can be 0
var vals []string
for i := 0; i < n; i++ {
vals = append(vals, randMVIndexValue(opts))
}
return "[" + strings.Join(vals, ", ") + "]"
}

type randMVIndexValOpts struct {
valType string // INT, UNSIGNED, STR, DATE
maxStrLen int
Expand Down

0 comments on commit 0a1d0c5

Please sign in to comment.