Skip to content

Commit

Permalink
planner: add test cases for keep_order and no_keep_order hints (#40321)
Browse files Browse the repository at this point in the history
ref #39964
  • Loading branch information
Reminiscent authored Jan 10, 2023
1 parent f771c67 commit c4d8ed1
Show file tree
Hide file tree
Showing 3 changed files with 482 additions and 3 deletions.
56 changes: 54 additions & 2 deletions planner/core/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1330,9 +1330,13 @@ func TestKeepOrderHint(t *testing.T) {

tk.MustExec("use test")
tk.MustExec("set tidb_cost_model_version=2")
tk.MustExec("drop table if exists t, t1, t2")
tk.MustExec("drop table if exists t, t1, th")
tk.MustExec("drop view if exists v, v1")
tk.MustExec("create table t(a int, b int, primary key(a));")
tk.MustExec("create table t1(a int, b int, index idx_a(a), index idx_b(b));")
tk.MustExec("create table t1(a int, b int, index idx_a(a));")
tk.MustExec("create table th (a int, key(a)) partition by hash(a) partitions 4;")
tk.MustExec("create definer='root'@'localhost' view v as select * from t1 where a<10 order by a limit 1;")
tk.MustExec("create definer='root'@'localhost' view v1 as select * from t where a<10 order by a limit 1;")

// If the optimizer can not generate the keep order plan, it will report error
err := tk.ExecToErr("explain select /*+ keep_order(t1, idx_a) */ * from t1 where a<10 limit 1;")
Expand All @@ -1341,6 +1345,14 @@ func TestKeepOrderHint(t *testing.T) {
err = tk.ExecToErr("explain select /*+ keep_order(t, primary) */ * from t where a<10 limit 1;")
require.EqualError(t, err, "[planner:1815]Internal : Can't find a proper physical plan for this query")

// The partition table can not keep order
tk.MustExec("analyze table th;")
err = tk.ExecToErr("select a from th where a<1 order by a limit 1;")
require.NoError(t, err)

err = tk.ExecToErr("select /*+ keep_order(th, a) */ a from th where a<1 order by a limit 1;")
require.EqualError(t, err, "[planner:1815]Internal : Can't find a proper physical plan for this query")

var input []string
var output []struct {
SQL string
Expand All @@ -1361,6 +1373,46 @@ func TestKeepOrderHint(t *testing.T) {
}
}

func TestKeepOrderHintWithBinding(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)

tk.MustExec("use test")
tk.MustExec("set tidb_cost_model_version=2")
tk.MustExec("drop table if exists t1")
tk.MustExec("create table t1(a int, b int, index idx_a(a));")

// create binding for keep_order hint
tk.MustExec("select * from t1 where a<10 order by a limit 1;")
tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("0"))
tk.MustExec("create global binding for select * from t1 where a<10 order by a limit 1 using select /*+ keep_order(t1, idx_a) */ * from t1 where a<10 order by a limit 1;")
tk.MustExec("select * from t1 where a<10 order by a limit 1;")
tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1"))
res := tk.MustQuery("show global bindings").Rows()
require.Equal(t, res[0][0], "select * from `test` . `t1` where `a` < ? order by `a` limit ?")
require.Equal(t, res[0][1], "SELECT /*+ keep_order(`t1` `idx_a`)*/ * FROM `test`.`t1` WHERE `a` < 10 ORDER BY `a` LIMIT 1")

tk.MustExec("drop global binding for select * from t1 where a<10 order by a limit 1;")
tk.MustExec("select * from t1 where a<10 order by a limit 1;")
tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("0"))
res = tk.MustQuery("show global bindings").Rows()
require.Equal(t, len(res), 0)

// create binding for no_keep_order hint
tk.MustExec("create global binding for select * from t1 where a<10 order by a limit 1 using select /*+ no_keep_order(t1, idx_a) */ * from t1 where a<10 order by a limit 1;")
tk.MustExec("select * from t1 where a<10 order by a limit 1;")
tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1"))
res = tk.MustQuery("show global bindings").Rows()
require.Equal(t, res[0][0], "select * from `test` . `t1` where `a` < ? order by `a` limit ?")
require.Equal(t, res[0][1], "SELECT /*+ no_keep_order(`t1` `idx_a`)*/ * FROM `test`.`t1` WHERE `a` < 10 ORDER BY `a` LIMIT 1")

tk.MustExec("drop global binding for select * from t1 where a<10 order by a limit 1;")
tk.MustExec("select * from t1 where a<10 order by a limit 1;")
tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("0"))
res = tk.MustQuery("show global bindings").Rows()
require.Equal(t, len(res), 0)
}

func TestViewHint(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
Expand Down
45 changes: 44 additions & 1 deletion planner/core/testdata/integration_suite_in.json
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,50 @@
"explain select /*+ no_keep_order(t1, idx_a) */ * from t1 where a<10 order by a limit 1;",
"explain select /*+ no_keep_order(t, primary) */ * from t where a<10 order by a limit 1;",
"explain select /*+ no_keep_order(t1, idx_a) */ * from t1 where a<10 limit 1;",
"explain select /*+ no_keep_order(t, primary) */ * from t where a<10 limit 1;"
"explain select /*+ no_keep_order(t, primary) */ * from t where a<10 limit 1;",

// The index doesn't exist
"explain select /*+ keep_order(t1, idx_b) */ * from t1 where b<10 order by b limit 1;",
"explain select /*+ keep_order(t, idx_b) */ * from t where b<10 order by b limit 1;",
"explain select /*+ no_keep_order(t1, idx_b) */ * from t1 where b<10 order by b limit 1;",
"explain select /*+ no_keep_order(t, idx_b) */ * from t where b<10 order by b limit 1;",

// Use the keep_order/ no_keep_order with the use_index/ ignore_index/ force_index hint at the same time
"explain select /*+ keep_order(t1, idx_a) use_index(t1, idx_a) */ * from t1 where a<10 order by a limit 1;",
"explain select /*+ keep_order(t1, idx_a) */ * from t1 use index(idx_a) where a<10 order by a limit 1;",
"explain select /*+ keep_order(t1, idx_a) force_index(t1, idx_a) */ * from t1 where a<10 order by a limit 1;",
"explain select /*+ keep_order(t1, idx_a) */ * from t1 force index(idx_a) where a<10 order by a limit 1;",
"explain select /*+ keep_order(t1, idx_a) ignore_index(t1, idx_a) */ * from t1 where a<10 order by a limit 1;",

"explain select /*+ keep_order(t, primary) use_index(t, primary) */ * from t where a<10 order by a limit 1;",
"explain select /*+ keep_order(t, primary) */ * from t use index(primary) where a<10 order by a limit 1;",
"explain select /*+ keep_order(t, primary) force_index(t, primary) */ * from t where a<10 order by a limit 1;",
"explain select /*+ keep_order(t, primary) */ * from t force index(primary) where a<10 order by a limit 1;",
"explain select /*+ keep_order(t, primary) ignore_index(t, primary) */ * from t where a<10 order by a limit 1;",

"explain select /*+ no_keep_order(t, primary) use_index(t, primary) */ * from t where a<10 order by a limit 1;",
"explain select /*+ no_keep_order(t, primary) */ * from t use index(primary) where a<10 order by a limit 1;",
"explain select /*+ no_keep_order(t, primary) force_index(t, primary) */ * from t where a<10 order by a limit 1;",
"explain select /*+ no_keep_order(t, primary) */ * from t force index(primary) where a<10 order by a limit 1;",
"explain select /*+ no_keep_order(t, primary) ignore_index(t, primary) */ * from t where a<10 order by a limit 1;",

"explain select /*+ no_keep_order(t1, idx_a) use_index(t1, idx_a) */ * from t1 where a<10 order by a limit 1;",
"explain select /*+ no_keep_order(t1, idx_a) */ * from t1 use index(idx_a) where a<10 order by a limit 1;",
"explain select /*+ no_keep_order(t1, idx_a) force_index(t1, idx_a) */ * from t1 where a<10 order by a limit 1;",
"explain select /*+ no_keep_order(t1, idx_a) */ * from t1 force index(idx_a) where a<10 order by a limit 1;",
"explain select /*+ no_keep_order(t1, idx_a) ignore_index(t1, idx_a) */ * from t1 where a<10 order by a limit 1;",

// Use the keep_order/ no_keep_order with the use_view hint at the same time
"explain select /*+ qb_name(qb, v) keep_order(t1@qb, idx_a) */ * from v",
"explain select /*+ qb_name(qb, v1) keep_order(t@qb, primary) */ * from v1",
"explain select /*+ qb_name(qb, v) no_keep_order(t1@qb, idx_a) */ * from v",
"explain select /*+ qb_name(qb, v1) no_keep_order(t@qb, primary) */ * from v1",

// Use the keep_order/ no_keep_order with CTE at the same time
"explain WITH CTE AS (select /*+ keep_order(t1, idx_a) */ * from t1 where a<10 order by a limit 1) SELECT * FROM CTE WHERE CTE.a <18 union select * from cte where cte.b > 1;",
"explain WITH CTE AS (select /*+ keep_order(t, primary) */ * from t where a<10 order by a limit 1) SELECT * FROM CTE WHERE CTE.a <18 union select * from cte where cte.b > 1;",
"explain WITH CTE AS (select /*+ no_keep_order(t1, idx_a) */ * from t1 where a<10 order by a limit 1) SELECT * FROM CTE WHERE CTE.a <18 union select * from cte where cte.b > 1;",
"explain WITH CTE AS (select /*+ no_keep_order(t, primary) */ * from t where a<10 order by a limit 1) SELECT * FROM CTE WHERE CTE.a <18 union select * from cte where cte.b > 1;"
]
},
{
Expand Down
Loading

0 comments on commit c4d8ed1

Please sign in to comment.