[
  {
    "name": "TestMPPHints",
    "cases": [
      "select /*+ read_from_storage(tiflash[t]), MPP_1PHASE_AGG() */ a, sum(b) from t group by a, c",
      "select /*+ read_from_storage(tiflash[t]), MPP_2PHASE_AGG() */ a, sum(b) from t group by a, c",
      "select /*+ read_from_storage(tiflash[t1, t2]), shuffle_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a",
      "select /*+ read_from_storage(tiflash[t1, t2]), broadcast_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a"
    ]
  },
  {
    "name": "TestHintScope",
    "cases": [
      // join hints
      "select /*+ MERGE_JOIN(t1) */ t1.a, t1.b from t t1, (select /*+ INL_JOIN(t3) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
      "select /*+ MERGE_JOIN(test.t1) */ t1.a, t1.b from t t1, (select /*+ INL_JOIN(test.t3) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
      "select /*+ MERGE_JOIN(t1) */ t1.a, t1.b from t t1, (select /*+ HASH_JOIN(t2) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
      "select /*+ INL_JOIN(t1) */ t1.a, t1.b from t t1, (select /*+ HASH_JOIN(t2) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
      "select /*+ INL_JOIN(test.t1) */ t1.a, t1.b from t t1, (select /*+ HASH_JOIN(test.t2) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
      "select /*+ INL_JOIN(t1) */ t1.a, t1.b from t t1, (select /*+ MERGE_JOIN(t2) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
      "select /*+ HASH_JOIN(t1) */ t1.a, t1.b from t t1, (select /*+ MERGE_JOIN(t2) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
      "select /*+ HASH_JOIN(test.t1) */ t1.a, t1.b from t t1, (select /*+ MERGE_JOIN(test.t2) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
      "select /*+ HASH_JOIN(t1) */ t1.a, t1.b from t t1, (select /*+ INL_JOIN(t2) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
      "select /*+ MERGE_JOIN(t1) */ t1.a, t1.b from t t1, (select t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
      "select /*+ INL_JOIN(t1) */ t1.a, t1.b from t t1, (select t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
      "select /*+ HASH_JOIN(t1) */ t1.a, t1.b from t t1, (select t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
      "select /*+ HASH_JOIN(@sel_2 t1@sel_2, t2@sel_2), MERGE_JOIN(@sel_1 t1@sel_1, t2@sel_1) */ * from (select t1.a, t1.b from t t1, t t2 where t1.a = t2.a) t1, t t2 where t1.b = t2.b",
      // aggregation hints
      "select /*+ STREAM_AGG() */ s, count(s) from (select /*+ HASH_AGG() */ sum(t1.a) as s from t t1, t t2 where t1.a = t2.b group by t1.a) p group by s",
      "select /*+ HASH_AGG() */ s, count(s) from (select /*+ STREAM_AGG() */ sum(t1.a) as s from t t1, t t2 where t1.a = t2.b group by t1.a) p group by s",
      "select /*+ HASH_AGG() */ s, count(s) from (select sum(t1.a) as s from t t1, t t2 where t1.a = t2.b group by t1.a) p group by s",
      "select /*+ STREAM_AGG() */ s, count(s) from (select sum(t1.a) as s from t t1, t t2 where t1.a = t2.b group by t1.a) p group by s"
    ]
  },
  {
    "name": "TestIndexHint",
    "cases": [
      // simple case
      "select /*+ USE_INDEX(t, c_d_e) */ * from t",
      "select /*+ USE_INDEX(test.t, c_d_e) */ * from t",
      "select /*+ IGNORE_INDEX(t, c_d_e) */ c from t order by c",
      "select /*+ IGNORE_INDEX(test.t, c_d_e) */ c from t order by c",
      "select /*+ FORCE_INDEX(t, c_d_e) */ * from t",
      "select /*+ FORCE_INDEX(test.t, c_d_e) */ * from t",
      "select /*+ USE_INDEX(t, c_d_e) */ * from t t1",
      "select /*+ IGNORE_INDEX(t, c_d_e) */ t1.c from t t1 order by t1.c",
      "select /*+ FORCE_INDEX(t, c_d_e) */ * from t t1",
      "select /*+ USE_INDEX(t1, c_d_e) */ * from t t1",
      "select /*+ IGNORE_INDEX(t1, c_d_e) */ t1.c from t t1 order by t1.c",
      "select /*+ FORCE_INDEX(t1, c_d_e) */ * from t t1",
      "select /*+ USE_INDEX(t1, c_d_e), USE_INDEX(t2, f) */ * from t t1, t t2 where t1.a = t2.b",
      "select /*+ IGNORE_INDEX(t1, c_d_e), IGNORE_INDEX(t2, f), HASH_JOIN(t1) */ * from t t1, t t2 where t1.a = t2.b",
      "select /*+ FORCE_INDEX(t1, c_d_e), FORCE_INDEX(t2, f) */ * from t t1, t t2 where t1.a = t2.b",
      // test multiple indexes
      "select /*+ USE_INDEX(t, c_d_e, f, g) */ * from t order by f",
      "select /*+ FORCE_INDEX(t, c_d_e, f, g) */ * from t order by f",
      // use TablePath when the hint only contains table.
      "select /*+ USE_INDEX(t) */ f from t where f > 10",
      "select /*+ FORCE_INDEX(t) */ f from t where f > 10",
      // there will be a warning instead of error when index not exist
      "select /*+ USE_INDEX(t, no_such_index) */ * from t",
      "select /*+ IGNORE_INDEX(t, no_such_index) */ * from t",
      "select /*+ FORCE_INDEX(t, no_such_index) */ * from t",
      // use both use_index and ignore_index, same as index hints in sql.
      "select /*+ USE_INDEX(t, c_d_e), IGNORE_INDEX(t, f) */ c from t order by c",
      "select /*+ USE_INDEX(t, f), IGNORE_INDEX(t, f) */ c from t order by c",
      "select /*+ USE_INDEX(t, c_d_e), IGNORE_INDEX(t, c_d_e) */ c from t order by c",
      "select /*+ USE_INDEX(t, c_d_e, f), IGNORE_INDEX(t, c_d_e) */ c from t order by c",
      // use both force_index and ignore_index, same as index hints in sql.
      "select /*+ FORCE_INDEX(t, c_d_e), IGNORE_INDEX(t, f) */ c from t order by c",
      "select /*+ FORCE_INDEX(t, f), IGNORE_INDEX(t, f) */ c from t order by c",
      "select /*+ FORCE_INDEX(t, c_d_e), IGNORE_INDEX(t, c_d_e) */ c from t order by c",
      "select /*+ FORCE_INDEX(t, c_d_e, f), IGNORE_INDEX(t, c_d_e) */ c from t order by c"
    ]
  },
  {
    "name": "TestIndexMergeHint",
    "cases": [
      "select /*+ USE_INDEX_MERGE(t, c_d_e, f_g) */ * from t where c < 1 or f > 2",
      "select /*+ USE_INDEX_MERGE(t, primary, f_g) */ * from t where a < 1 or f > 2",
      "select /*+ USE_INDEX_MERGE(t, primary, f_g, c_d_e) */ * from t where a < 1 or f > 2",
      "select /*+ NO_INDEX_MERGE(), USE_INDEX_MERGE(t, primary, f_g, c_d_e) */ * from t where a < 1 or f > 2",
      "select /*+ USE_INDEX_MERGE(t1, c_d_e, f_g) */ * from t where c < 1 or f > 2",
      "select /*+ NO_INDEX_MERGE(), USE_INDEX_MERGE(t, primary, f_g, c_d_e) */ * from t where a < 1 or f > 2",
      "select /*+ USE_INDEX_MERGE(t) USE_INDEX_MERGE(t) */ * from t where c < 1 or f > 2",
      "select /*+ USE_INDEX_MERGE(db2.t) */ * from t where c < 1 or f > 2",
      "select /*+ USE_INDEX_MERGE(db2.t, c_d_e, f_g) */ * from t where c < 1 or f > 2"
    ]
  },
  {
    "name": "TestDAGPlanBuilderSimpleCase",
    "cases":[
      // Test index hint.
      "select * from t t1 use index(c_d_e)",
      "select f from t use index() where f = 1",
      // Test ts + Sort vs. DoubleRead + filter.
      "select a from t where a between 1 and 2 order by c",
      // Test DNF condition + Double Read.
      "select * from t where (t.c > 0 and t.c < 2) or (t.c > 4 and t.c < 6) or (t.c > 8 and t.c < 10) or (t.c > 12 and t.c < 14) or (t.c > 16 and t.c < 18)",
      "select * from t where (t.c > 0 and t.c < 1) or (t.c > 2 and t.c < 3) or (t.c > 4 and t.c < 5) or (t.c > 6 and t.c < 7) or (t.c > 9 and t.c < 10)",
      // Test TopN to table branch in double read.
      "select * from t where t.c = 1 and t.e = 1 order by t.b limit 1",
      // Test Null Range
      "select * from t where t.e_str is null",
      // Test Null Range but the column has not null flag.
      "select * from t where t.c is null",
      // Test TopN to index branch in double read.
      "select * from t where t.c = 1 and t.e = 1 order by t.e limit 1",
      // Test TopN to Limit in double read.
      "select * from t where t.c = 1 and t.e = 1 order by t.d limit 1",
      // Test TopN to Limit in index single read.
      "select c from t where t.c = 1 and t.e = 1 order by t.d limit 1",
      // Test TopN to Limit in table single read.
      "select c from t order by t.a limit 1",
      // Test TopN push down in table single read.
      "select c from t order by t.a + t.b limit 1",
      // Test Limit push down in table single read.
      "select c from t  limit 1",
      // Test Limit push down in index single read.
      "select c from t where c = 1 limit 1",
      // Test index single read and Selection.
      "select c from t where c = 1",
      // Test index single read and Sort.
      "select c from t order by c",
      // Test index single read and Sort.
      "select c from t where c = 1 order by e",
      // Test Limit push down in double single read.
      "select c, b from t where c = 1 limit 1",
      // Test Selection + Limit push down in double single read.
      "select c, b from t where c = 1 and e = 1 and b = 1 limit 1",
      // Test Order by multi columns.
      "select c from t where c = 1 order by d, c",
      // Test for index with length.
      "select c_str from t where e_str = '1' order by d_str, c_str",
      // Test PK in index single read.
      "select c from t where t.c = 1 and t.a > 1 order by t.d limit 1",
      // Test composed index.
      // FIXME: The TopN didn't be pushed.
      "select c from t where t.c = 1 and t.d = 1 order by t.a limit 1",
      // Test PK in index double read.
      "select * from t where t.c = 1 and t.a > 1 order by t.d limit 1",
      // Test index filter condition push down.
      "select * from t use index(e_d_c_str_prefix) where t.c_str = 'abcdefghijk' and t.d_str = 'd' and t.e_str = 'e'",
      "select * from t use index(e_d_c_str_prefix) where t.e_str = b'1110000'",
      "select * from (select * from t use index() order by b) t left join t t1 on t.a=t1.a limit 10",
      // Test embedded ORDER BY which imposes on different number of columns than outer query.
      "select * from ((SELECT 1 a,3 b) UNION (SELECT 2,1) ORDER BY (SELECT 2)) t order by a,b",
      "select * from ((SELECT 1 a,6 b) UNION (SELECT 2,5) UNION (SELECT 2, 4) ORDER BY 1) t order by 1, 2",
      "select * from (select *, NULL as xxx from t) t order by xxx",
      "select * from t use index(f) where f = 1 and a = 1",
      "select * from t2 use index(b) where b = 1 and a = 1",
      // Test inline project for Limit
      "select f from t where a > 1",
      "select f from t where a > 1 limit 10"
    ]
  },
  {
    "name": "TestDAGPlanBuilderJoin",
    "cases": [
      "select * from t t1 join t t2 on t1.a = t2.c_str",
      "select * from t t1 join t t2 on t1.b = t2.a",
      "select * from t t1 join t t2 on t1.a = t2.a join t t3 on t1.a = t3.a",
      "select * from t t1 join t t2 on t1.a = t2.a join t t3 on t1.b = t3.a",
      "select * from t t1 join t t2 on t1.b = t2.a order by t1.a",
      "select * from t t1 join t t2 on t1.b = t2.a order by t1.a limit 1",
      // Test hash join's hint.
      "select /*+ TIDB_HJ(t1, t2) */ * from t t1 join t t2 on t1.b = t2.a order by t1.a limit 1",
      "select * from t t1 left join t t2 on t1.b = t2.a where 1 = 1 limit 1",
      "select * from t t1 join t t2 on t1.b = t2.a and t1.c = 1 and t1.d = 1 and t1.e = 1 order by t1.a limit 1",
      "select * from t t1 join t t2 on t1.b = t2.b join t t3 on t1.b = t3.b",
      "select * from t t1 join t t2 on t1.a = t2.a order by t1.a",
      "select * from t t1 left outer join t t2 on t1.a = t2.a right outer join t t3 on t1.a = t3.a",
      "select * from t t1 join t t2 on t1.a = t2.a join t t3 on t1.a = t3.a and t1.b = 1 and t3.c = 1",
      "select * from t where t.c in (select b from t s where s.a = t.a)",
      "select t.c in (select b from t s where s.a = t.a) from t",
      // Test Single Merge Join.
      // Merge Join now enforce a sort.
      "select /*+ TIDB_SMJ(t1,t2)*/ * from t t1, t t2 where t1.a = t2.b",
      "select /*+ TIDB_SMJ(t1,t2)*/ * from t t1, t t2 where t1.a = t2.a",
      // Test Single Merge Join + Sort.
      "select /*+ TIDB_SMJ(t1,t2)*/ * from t t1, t t2 where t1.a = t2.a order by t2.a",
      "select /*+ TIDB_SMJ(t1,t2)*/ * from t t1, t t2 where t1.b = t2.b order by t2.a",
      // Test Single Merge Join + Sort + desc.
      "select /*+ TIDB_SMJ(t1,t2)*/ * from t t1, t t2 where t1.a = t2.a order by t2.a desc",
      "select /*+ TIDB_SMJ(t1,t2)*/ * from t t1, t t2 where t1.b = t2.b order by t2.b desc",
      // Test Multi Merge Join.
      "select /*+ TIDB_SMJ(t1,t2,t3)*/ * from t t1, t t2, t t3 where t1.a = t2.a and t2.a = t3.a",
      "select /*+ TIDB_SMJ(t1,t2,t3)*/ * from t t1, t t2, t t3 where t1.a = t2.b and t2.a = t3.b",
      // Test Multi Merge Join with multi keys.
      // TODO: More tests should be added.
      "select /*+ TIDB_SMJ(t1,t2,t3)*/ * from t t1, t t2, t t3 where t1.c = t2.c and t1.d = t2.d and t3.c = t1.c and t3.d = t1.d",
      "select /*+ TIDB_SMJ(t1,t2,t3)*/ * from t t1, t t2, t t3 where t1.c = t2.c and t1.d = t2.d and t3.c = t1.c and t3.d = t1.d order by t1.c",
      // Test Multi Merge Join + Outer Join.
      "select /*+ TIDB_SMJ(t1,t2,t3)*/ * from t t1 left outer join t t2 on t1.a = t2.a left outer join t t3 on t2.a = t3.a",
      "select /*+ TIDB_SMJ(t1,t2,t3)*/ * from t t1 left outer join t t2 on t1.a = t2.a left outer join t t3 on t1.a = t3.a",
      // Test Index Join + TableScan.
      "select /*+ TIDB_INLJ(t1, t2) */ * from t t1, t t2 where t1.a = t2.a",
      // Test Index Join + DoubleRead.
      "select /*+ TIDB_INLJ(t2) */ * from t t1, t t2 where t1.a = t2.c",
      // Test Index Join + SingleRead.
      "select /*+ TIDB_INLJ(t2) */ t1.a , t2.a from t t1, t t2 where t1.a = t2.c",
      // Test Index Join + Order by.
      "select /*+ TIDB_INLJ(t1, t2) */ t1.a, t2.a from t t1, t t2 where t1.a = t2.a order by t1.c",
      // Test Index Join + Order by.
      "select /*+ TIDB_INLJ(t1, t2) */ t1.a, t2.a from t t1, t t2 where t1.a = t2.a order by t2.c",
      // Test Index Join + TableScan + Rotate.
      "select /*+ TIDB_INLJ(t1) */ t1.a , t2.a from t t1, t t2 where t1.a = t2.c",
      // Test Index Join + OuterJoin + TableScan.
      "select /*+ TIDB_INLJ(t1, t2) */ * from t t1 left outer join t t2 on t1.a = t2.a and t2.b < 1",
      "select /*+ TIDB_INLJ(t1, t2) */ * from t t1 join t t2 on t1.d=t2.d and t2.c = 1",
      // Test Index Join failed.
      "select /*+ TIDB_INLJ(t1, t2) */ * from t t1 left outer join t t2 on t1.a = t2.b",
      // Test Index Join failed.
      "select /*+ TIDB_INLJ(t2) */ * from t t1 right outer join t t2 on t1.a = t2.b",
      // Test Semi Join hint success.
      "select /*+ TIDB_INLJ(t2) */ * from t t1 where t1.a in (select a from t t2)",
      // Test Semi Join hint fail.
      "select /*+ TIDB_INLJ(t1) */ * from t t1 where t1.a in (select a from t t2)",
      "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t1.c=t2.c and t1.f=t2.f",
      "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t1.a = t2.a and t1.f=t2.f",
      "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t1.f=t2.f and t1.a=t2.a",
      "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t1.a=t2.a and t2.a in (1, 2)",
      "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t1.b=t2.c and t1.b=1 and t2.d > t1.d-10 and t2.d < t1.d+10",
      "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t1.b=t2.b and t1.c=1 and t2.c=1 and t2.d > t1.d-10 and t2.d < t1.d+10",
      "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t2.c > t1.d-10 and t2.c < t1.d+10",
      "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t1.b = t2.c and t2.c=1 and t2.d=2 and t2.e=4",
      "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t2.c=1 and t2.d=1 and t2.e > 10 and t2.e < 20"
    ]
  },
  {
    "name": "TestDAGPlanBuilderSubquery",
    "cases": [
      // Test join key with cast.
      "select * from t where exists (select s.a from t s having sum(s.a) = t.a )",
      "select * from t where exists (select s.a from t s having sum(s.a) = t.a ) order by t.a",
      // FIXME: Report error by resolver.
      // "select * from t where exists (select s.a from t s having s.a = t.a ) order by t.a",
      "select * from t where a in (select s.a from t s) order by t.a",
      // Test Nested sub query.
      "select * from t where exists (select s.a from t s where s.c in (select c from t as k where k.d = s.d) having sum(s.a) = t.a )",
      // Test Semi Join + Order by.
      "select * from t where a in (select a from t) order by b",
      // Test Apply.
      "select t.c in (select count(*) from t s, t t1 where s.a = t.a and s.a = t1.a) from t",
      "select (select count(*) from t s, t t1 where s.a = t.a and s.a = t1.a) from t",
      "select (select count(*) from t s, t t1 where s.a = t.a and s.a = t1.a) from t order by t.a"
    ]
  },
  {
    "name": "TestDAGPlanTopN",
    "cases": [
      "select * from t t1 left join t t2 on t1.b = t2.b left join t t3 on t2.b = t3.b order by t1.a limit 1",
      "select * from t t1 left join t t2 on t1.b = t2.b left join t t3 on t2.b = t3.b order by t1.b limit 1",
      "select * from t t1 left join t t2 on t1.b = t2.b left join t t3 on t2.b = t3.b limit 1",
      "select * from t where b = 1 and c = 1 order by c limit 1",
      "select * from t where c = 1 order by c limit 1",
      "select * from t order by a limit 1",
      "select c from t order by c limit 1"
    ]
  },
  {
    "name": "TestDAGPlanBuilderBasePhysicalPlan",
    "cases": [
      // Test for update.
      // TODO: This is not reasonable. Mysql do like this because the limit of InnoDB, should TiDB keep consistency with MySQL?
      "select * from t order by b limit 1 for update",
      // Test complex update.
      "update t set a = 5 where b < 1 order by d limit 1",
      // Test simple update.
      "update t set a = 5",
      // TODO: Test delete/update with join.
      // Test join hint for delete and update
      "delete /*+ TIDB_INLJ(t1, t2) */ t1 from t t1, t t2 where t1.c=t2.c",
      "delete /*+ TIDB_SMJ(t1, t2) */ from t1 using t t1, t t2 where t1.c=t2.c",
      "update /*+ TIDB_SMJ(t1, t2) */ t t1, t t2 set t1.c=1, t2.c=1 where t1.a=t2.a",
      "update /*+ TIDB_HJ(t1, t2) */ t t1, t t2 set t1.c=1, t2.c=1 where t1.a=t2.a",
      // Test complex delete.
      "delete from t where b < 1 order by d limit 1",
      // Test simple delete.
      "delete from t",
      // Test "USE INDEX" hint in delete statement from single table
      "delete from t use index(c_d_e) where b = 1",
      // Test complex insert.
      "insert into t select * from t where b < 1 order by d limit 1",
      // Test simple insert.
      "insert into t (a, b, c, e, f, g) values(0,0,0,0,0,0)",
      // Test dual.
      "select 1",
      "select * from t where false",
      // Test show.
      "show tables"
    ]
  },
  {
    "name": "TestDAGPlanBuilderUnion",
    "cases": [
      // Test simple union.
      "select * from t union all select * from t",
      // Test Order by + Union.
      "select * from t union all (select * from t) order by a ",
      // Test Limit + Union.
      "select * from t union all (select * from t) limit 1",
      // Test TopN + Union.
      "select a from t union all (select c from t) order by a limit 1"
    ]
  },
  {
    "name": "TestDAGPlanBuilderUnionScan",
    "cases": [
      // Read table.
      "select * from t",
      "select * from t where b = 1",
      "select * from t where a = 1",
      "select * from t where a = 1 order by a",
      "select * from t where a = 1 order by b",
      "select * from t where a = 1 limit 1",
      "select * from t where c = 1",
      "select c from t where c = 1"
    ]
  },
  {
    "name": "TestDAGPlanBuilderAgg",
    "cases": [
      // Test distinct.
      "select distinct b from t",
      "select count(*) from (select * from t order by b) t group by b",
      "select count(*), x from (select b as bbb, a + 1 as x from (select * from t order by b) t) t group by bbb",
      // Test agg + table.
      "select sum(a), avg(b + c) from t group by d",
      "select sum(distinct a), avg(b + c) from t group by d",
      //  Test group by (c + d)
      "select sum(e), avg(e + c) from t where c = 1 group by (c + d)",
      // Test stream agg + index single.
      "select sum(e), avg(e + c) from t where c = 1 group by c",
      // Test hash agg + index single.
      "select sum(e), avg(e + c) from t where c = 1 group by e",
      // Test hash agg + index double.
      "select sum(e), avg(b + c) from t where c = 1 and e = 1 group by d",
      // Test stream agg + index double.
      "select sum(e), avg(b + c) from t where c = 1 and b = 1",
      // Test hash agg + order.
      "select sum(e) as k, avg(b + c) from t where c = 1 and b = 1 and e = 1 group by d order by k",
      // Test stream agg + order.
      "select sum(e) as k, avg(b + c) from t where c = 1 and b = 1 and e = 1 group by c order by k",
      // Test agg can't push down.
      "select sum(to_base64(e)) from t where c = 1",
      "select (select count(1) k from t s where s.a = t.a having k != 0) from t",
      // Test stream agg with multi group by columns.
      "select sum(to_base64(e)) from t group by e,d,c order by c",
      "select sum(e+1) from t group by e,d,c order by c",
      "select sum(to_base64(e)) from t group by e,d,c order by c,e",
      "select sum(e+1) from t group by e,d,c order by c,e",
      // Test stream agg + limit or sort
      "select count(*) from t group by g order by g limit 10",
      "select count(*) from t group by g limit 10",
      "select count(*) from t group by g order by g",
      "select count(*) from t group by g order by g desc limit 1",
      // Test hash agg + limit or sort
      "select count(*) from t group by b order by b limit 10",
      "select count(*) from t group by b order by b",
      "select count(*) from t group by b limit 10",
      // Test merge join + stream agg
      "select sum(a.g), sum(b.g) from t a join t b on a.g = b.g group by a.g",
      // Test index join + stream agg
      "select /*+ tidb_inlj(a,b) */ sum(a.g), sum(b.g) from t a join t b on a.g = b.g and a.g > 60 group by a.g order by a.g limit 1",
      "select sum(a.g), sum(b.g) from t a join t b on a.g = b.g and a.a>5 group by a.g order by a.g limit 1",
      "select sum(d) from t"
    ]
  },
  {
    "name": "TestRefine",
    "cases": [
      "select a from t where c is not null",
      "select a from t where c >= 4",
      "select a from t where c <= 4",
      "select a from t where c = 4 and d = 5 and e = 6",
      "select a from t where d = 4 and c = 5",
      "select a from t where c = 4 and e < 5",
      "select a from t where c = 4 and d <= 5 and d > 3",
      "select a from t where d <= 5 and d > 3",
      "select a from t where c between 1 and 2",
      "select a from t where c not between 1 and 2",
      "select a from t where c <= 5 and c >= 3 and d = 1",
      "select a from t where c = 1 or c = 2 or c = 3",
      "select b from t where c = 1 or c = 2 or c = 3 or c = 4 or c = 5",
      "select a from t where c = 5",
      "select a from t where c = 5 and b = 1",
      "select a from t where not a",
      "select a from t where c in (1)",
      "select a from t where c in ('1')",
      "select a from t where c = 1.0",
      "select a from t where c in (1) and d > 3",
      "select a from t where c in (1, 2, 3) and (d > 3 and d < 4 or d > 5 and d < 6)",
      "select a from t where c in (1, 2, 3) and (d > 2 and d < 4 or d > 5 and d < 7)",
      "select a from t where c in (1, 2, 3)",
      "select a from t where c in (1, 2, 3) and d in (1,2) and e = 1",
      "select a from t where d in (1, 2, 3)",
      "select a from t where c not in (1)",
      "select a from t use index(c_d_e) where c != 1",
      // test like
      "select a from t where c_str like ''",
      "select a from t where c_str like 'abc'",
      "select a from t where c_str not like 'abc'",
      "select a from t where not (c_str like 'abc' or c_str like 'abd')",
      "select a from t where c_str like '_abc'",
      "select a from t where c_str like 'abc%'",
      "select a from t where c_str like 'abc_'",
      "select a from t where c_str like 'abc%af'",
      "select a from t where c_str like 'abc\\_' escape ''",
      "select a from t where c_str like 'abc\\_'",
      "select a from t where c_str like 'abc\\\\_'",
      "select a from t where c_str like 'abc\\_%'",
      "select a from t where c_str like 'abc=_%' escape '='",
      "select a from t where c_str like 'abc\\__'",
      // Check that 123 is converted to string '123'. index can be used.
      "select a from t where c_str like 123",
      "select a from t where c = 1.9 and d > 3",
      "select a from t where c < 1.1",
      "select a from t where c <= 1.9",
      "select a from t where c >= 1.1",
      "select a from t where c > 1.9",
      "select a from t where c = 123456789098765432101234",
      "select a from t where c = 'hanfei'"
    ]
  },
  {
    "name": "TestAggEliminator",
    "cases": [
      // Max to Limit + Sort-Desc.
      "select max(a) from t;",
      // Min to Limit + Sort.
      "select min(a) from t;",
      // Min to Limit + Sort, and isnull() should be added.
      "select min(c_str) from t;",
      // Do nothing to max + firstrow.
      "select max(a), b from t;",
      // If max/min contains scalar function, we can still do transformation.
      "select max(a+1) from t;",
      // Min + Max to Limit + Sort + Join.
      "select max(a), min(a) from t;",
      // Min + Max with range condition.
      "select max(a), min(a) from t where a > 10",
      // Min + Max with unified index range condition.
      "select max(d), min(d) from t where c = 1 and d > 10",
      // Min + Max with multiple columns
      "select max(a), max(c), min(f) from t",
      // Do nothing if any column has no index.
      "select max(a), max(b) from t",
      // Do nothing if any column has a non-range condition.
      "select max(a), max(c) from t where c > 10",
      // Do nothing if the condition cannot be pushed down to range.
      "select max(a), min(a) from t where a * 3 + 10 < 100",
      // Do nothing to max with groupby.
      "select max(a) from t group by b;",
      // If inner is not a data source, we can still do transformation.
      "select max(a) from (select t1.a from t t1 join t t2 on t1.a=t2.a) t"
    ]
  },
  {
    "name": "TestUnmatchedTableInHint",
    "cases": [
      "SELECT /*+ TIDB_SMJ(t3, t4) */ * from t t1, t t2 where t1.a = t2.a",
      "SELECT /*+ TIDB_HJ(t3, t4) */ * from t t1, t t2 where t1.a = t2.a",
      "SELECT /*+ TIDB_INLJ(t3, t4) */ * from t t1, t t2 where t1.a = t2.a",
      "SELECT /*+ TIDB_SMJ(t1, t2) */ * from t t1, t t2 where t1.a = t2.a",
      "SELECT /*+ TIDB_SMJ(t3, t4) */ * from t t1, t t2, t t3 where t1.a = t2.a and t2.a = t3.a"
    ]
  },
  {
    "name": "TestJoinHints",
    "cases": [
      "select /*+ TIDB_INLJ(t1) */ t1.a, t2.a, t3.a from t t1, t t2, t t3 where t1.a = t2.a and t2.a = t3.a;",
      "select /*+ TIDB_INLJ(test.t1) */ t1.a, t2.a, t3.a from t t1, t t2, t t3 where t1.a = t2.a and t2.a = t3.a;",
      "select /*+ TIDB_INLJ(t1) */ t1.b, t2.a from t t1, t t2 where t1.b = t2.a;",
      "select /*+ TIDB_INLJ(t2) */ t1.b, t2.a from t2 t1, t2 t2 where t1.b=t2.b and t2.c=-1;"
    ]
  },
  {
    "name":"TestAggregationHints",
    "cases": [
      // without Aggregation hints
      {"SQL": "select count(*) from t t1, t t2 where t1.a = t2.b"},
      {"SQL": "select count(t1.a) from t t1, t t2 where t1.a = t2.a*2 group by t1.a"},
      // with Aggregation hints
      {"SQL": "select /*+ HASH_AGG() */ count(*) from t t1, t t2 where t1.a = t2.b"},
      {"SQL": "select /*+ STREAM_AGG() */ count(t1.a) from t t1, t t2 where t1.a = t2.a*2 group by t1.a"},
      // test conflict warning
      {"SQL": "select /*+ HASH_AGG() STREAM_AGG() */ count(*) from t t1, t t2 where t1.a = t2.b"},
      {"SQL": "select /*+ STREAM_AGG() */ distinct a from t"},
      // additional test
      {"SQL": "select /*+ HASH_AGG() */ t1.a from t t1 where t1.a < any(select t2.b from t t2)"},
      {"SQL": "select /*+ hash_agg() */ t1.a from t t1 where t1.a != any(select t2.b from t t2)"},
      {"SQL": "select /*+ hash_agg() */ t1.a from t t1 where t1.a = all(select t2.b from t t2)"},
      {"SQL": "select /*+ STREAM_AGG() */ sum(t1.a) from t t1 join t t2 on t1.b = t2.b group by t1.b", "AggPushDown": true},
      {"SQL": "select /*+ STREAM_AGG() */ e, sum(b) from t group by e"}
    ]
  },
  {
    "name": "TestQueryBlockHint",
    "cases": [
      "select /*+ MERGE_JOIN(@sel_1 t1), INL_JOIN(@sel_2 t3) */ t1.a, t1.b from t t1, (select t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
      "select /*+ MERGE_JOIN(@sel_1 t1), INL_JOIN(@qb t3) */ t1.a, t1.b from t t1, (select /*+ QB_NAME(qb) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
      "select /*+ HASH_JOIN(@sel_1 t1), MERGE_JOIN(@sel_2 t2) */ t1.a, t1.b from t t1, (select t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
      "select /*+ HASH_JOIN(@sel_1 t1), MERGE_JOIN(@qb t2) */ t1.a, t1.b from t t1, (select /*+ QB_NAME(qb) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
      "select /*+ INL_JOIN(@sel_1 t1), HASH_JOIN(@sel_2 t2) */ t1.a, t1.b from t t1, (select t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
      "select /*+ INL_JOIN(@sel_1 t1), HASH_JOIN(@qb t2) */ t1.a, t1.b from t t1, (select /*+ QB_NAME(qb) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
      "select /*+ HASH_AGG(@sel_1), STREAM_AGG(@sel_2) */ count(*) from t t1 where t1.a < (select count(*) from t t2 where t1.a > t2.a)",
      "select /*+ STREAM_AGG(@sel_1), HASH_AGG(@qb) */ count(*) from t t1 where t1.a < (select /*+ QB_NAME(qb) */ count(*) from t t2 where t1.a > t2.a)",
      "select /*+ HASH_AGG(@sel_2) */ a, (select count(*) from t t1 where t1.b > t.a) from t where b > (select b from t t2 where t2.b = t.a limit 1)",
      "select /*+ HASH_JOIN(@sel_1 t1), HASH_JOIN(@sel_2 t1) */ t1.b, t2.a, t2.aa from t t1, (select t1.a as a, t2.a as aa from t t1, t t2) t2 where t1.a = t2.aa;",
      "select /*+ HASH_JOIN(@sel_2 t1@sel_2, t2@sel_2), MERGE_JOIN(@sel_1 t1@sel_1, t2@sel_1) */ * from (select t1.a, t1.b from t t1, t t2 where t1.a = t2.a) t1, t t2 where t1.b = t2.b"
    ]
  },
  {
    "name": "TestIndexJoinUnionScan",
    "cases": [
      [
        "insert into t values(1, 1)",
        // Test Index Join + UnionScan + TableScan.
        "explain format = 'brief' select /*+ TIDB_INLJ(t2) */ * from t t1, t t2 where t1.a = t2.a"
      ],
      [
        "insert into t values(1, 1)",
        // Test Index Join + UnionScan + DoubleRead.
        "explain format = 'brief' select /*+ TIDB_INLJ(t2) */ * from t t1, t t2 where t1.a = t2.b"
      ],
      [
        "insert into t values(1, 1)",
        // Test Index Join + UnionScan + IndexScan.
        "explain format = 'brief' select /*+ TIDB_INLJ(t2) */ t1.a , t2.b from t t1, t t2 where t1.a = t2.b"
      ],
      [
        "insert into tt values(1)",
        "explain format = 'brief' select /*+ TIDB_INLJ(t2) */ * from tt t1, tt t2 where t1.a = t2.a"
      ]
    ]
  },
  {
    "name": "TestMergeJoinUnionScan",
    "cases": [
      [
        "insert into t2 values (11, 'amazing merkle')",
        "insert into t2 values (12, 'amazing merkle')",
        // Test Merge Join + UnionScan + TableScan.
        "explain format = 'brief' select /*+ MERGE_JOIN(t1,t2) */ * from t1, t2 where t1.c_int = t2.c_int and t1.c_int = t2.c_int order by t1.c_int, t2.c_str;"
      ]
    ]
  },
  {
    "name": "TestSemiJoinToInner",
    "cases": [
      "select t1.a, (select count(t2.a) from t t2 where t2.g in (select t3.d from t t3 where t3.c = t1.a)) as agg_col from t t1;"
    ]
  },
  {
    "name": "TestIndexJoinHint",
    "cases": [
      "select /*+ INL_JOIN(t1) */ * from t1 join t2 on t1.a = t2.a;",
      "select /*+ INL_HASH_JOIN(t1) */ * from t1 join t2 on t1.a = t2.a;",
      "select /*+ INL_MERGE_JOIN(t1) */ * from t1 join t2 on t1.a = t2.a;",
      // Issue 15484
      "select /*+ inl_merge_join(t2) */ t1.a, t2.a from t t1 left join t t2 use index(g_2) on t1.g=t2.g",
      "select /*+inl_merge_join(t2)*/ t1.a, t2.a from t t1 left join t t2 use index(g_2) on t1.g=t2.g order by t1.a"
    ]
  },
  {
    "name": "TestAggToCopHint",
    "cases": [
      "select /*+ AGG_TO_COP(), HASH_AGG(), USE_INDEX(t) */ sum(a) from ta group by a",
      "select /*+ AGG_TO_COP(), USE_INDEX(t) */ sum(b) from ta group by b",
      "select /*+ AGG_TO_COP(), HASH_AGG(), USE_INDEX(t) */ distinct a from ta group by a",
      "select /*+ AGG_TO_COP(), HASH_AGG(), HASH_JOIN(t1), USE_INDEX(t1), USE_INDEX(t2) */ sum(t1.a) from ta t1, ta t2 where t1.a = t2.b group by t1.a"
    ]
  },
  {
    "name": "TestLimitToCopHint",
    "cases": [
      "select /*+ LIMIT_TO_COP() */ * from tn where a = 1 and b > 10 and b < 20 and c > 50 order by d limit 1",
      "select * from tn where a = 1 and b > 10 and b < 20 and c > 50 order by d limit 1",
      "select /*+ LIMIT_TO_COP() */ a from tn where a div 2 order by a limit 1",
      "select /*+ LIMIT_TO_COP() */ a from tn where a > 10 limit 1"
    ]
  },
  {
    "name": "TestCTEMergeHint",
    "cases": [
      "with cte as (select /*+ MERGE() */ * from tc where tc.a < 60) select * from cte where cte.a <18",
      "with cte as (select * from tc where tc.a < 60) select * from cte c1, cte c2 where c1.a <18",
      "with cte as (select /*+ MERGE() */ * from v) select * from cte",
      "WITH cte1 AS (SELECT /*+ MERGE() */ a FROM tc), cte2 AS (SELECT /*+ MERGE()*/ c FROM te) SELECT * FROM cte1 JOIN cte2 WHERE cte1.a = cte2.c;",
      "WITH cte1 AS (SELECT a FROM tc), cte2 AS (SELECT /*+ MERGE() */ c FROM te) SELECT * FROM cte1 JOIN cte2 WHERE cte1.a = cte2.c;",
      "with recursive cte1(c1) as (select 1 union select /*+ MERGE() */ c1 + 1 c1 from cte1 where c1 < 100) select * from cte1;",
      "WITH cte1 AS (SELECT * FROM t1) SELECT /*+ MERGE() */ * FROM cte1 join t2 on cte1.a = t2.b;",
      "with cte1 as (with cte3 as (select /*+ MERGE() */  * from t1),cte4 as (select /*+ MERGE() */ * from t2) select /*+ MERGE() */  * from cte3,cte4) ,cte2 as (select /*+ MERGE() */  * from t3) select * from cte1,cte2;",
      "with cte1 as (select * from tc), cte2 as (with cte3 as (select /*+ MERGE() */ * from te) ,cte4 as (select * from tc) select * from cte3,cte4) select * from cte2;",
      "with cte1 as (with cte2 as (select /*+ MERGE() */ * from te) ,cte3 as (select /*+ MERGE() */ * from tc) select /*+ MERGE() */ * from cte2,cte3) select * from cte1;",
      "with cte1 as (select * from t1), cte2 as (with cte3 as (with cte5 as (select * from t2),cte6 as (select * from t3) select * from cte5,cte6) ,cte4 as (select * from t4) select * from cte3,cte4) select * from cte1,cte2;",
      "with cte1 as (select /*+ MERGE() */  * from t1), cte2 as (with cte3 as (with cte5 as (select * from t2),cte6 as (select * from t3) select * from cte5,cte6) ,cte4 as (select * from t4) select * from cte3,cte4) select * from cte1,cte2;",
      "with cte1 as (select * from t1), cte2 as (with cte3 as (with cte5 as (select * from t2),cte6 as (select * from t3) select * from cte5,cte6) ,cte4 as (select /*+ MERGE() */ * from t4) select * from cte3,cte4) select * from cte1,cte2;",
      "with cte1 as (select * from t1), cte2 as (with cte3 as (with cte5 as (select * from t2),cte6 as (select /*+ MERGE() */ * from t3) select * from cte5,cte6) ,cte4 as (select * from t4) select * from cte3,cte4) select * from cte1,cte2;",
      "with cte2 as (with cte4 as (select * from tc) select * from te, cte4) select * from cte2;",
      "with cte2 as (with cte4 as (select /*+ merge() */ * from tc) select * from te, cte4) select * from cte2;",
      "with cte1 as (with cte2 as (with cte3 as (select  /*+ MERGE() */  * from t2) select  /*+ MERGE() */  * from cte3) select * from cte2,(select  /*+ MERGE() */ * from t1) ttt) select * from cte1;",
      "with cte1 as (with cte2 as (with cte3 as (select  /*+ MERGE() */  * from t2) select  /*+ MERGE() */  * from cte3) select * from cte2,(select * from t1) ttt) select * from cte1,(select  /*+ MERGE() */ * from t3) ttw;",
      "with cte1 as (with cte2 as (with cte3 as (select  /*+ MERGE() */  * from t2) select  /*+ MERGE() */  * from cte3) select * from cte2,(select * from t1) ttt) select * from cte1,(select * from t3) ttw;"
    ]
  },
  {
    "name": "TestForceInlineCTE",
    "cases": [
      "set tidb_opt_force_inline_cte=1; -- enable force inline CTE",
      "with cte as (select * from t) select * from cte; -- inline",
      "with cte as (select /*+ MERGE() */ * from t) select * from cte; -- inline",
      "with cte as (select * from t) select * from cte cte1, cte cte2; -- inline CTEs is used by multi consumers",
      "with cte1 as (select * from t), cte2 as (select a from cte1 group by a) select * from cte1, cte2; -- multi inline CTEs",
      "with recursive cte1(c1) as (select 1 union select c1 + 1 c1 from cte1 where c1 < 100) select * from cte1; -- Recursive CTE can not be inlined",
      "with cte1 as (with cte2 as (select * from t) select * from cte2) select * from cte1; -- non-recursive 'cte2' definition inside another non-recursive 'cte1'",
      "with recursive cte2(c1) as (with cte1 as (select * from t) select a c1 from cte1 union select c1+1 c1 from cte2 where c1 < 100) select * from cte2; -- non-recursive 'cte1' inside recursive 'cte2'",
      "with cte1 as (with recursive cte2(c1) as (select 1 union select c1 + 1 c1 from cte2 where c1 < 100) select * from cte2) select * from cte1; -- recursive 'cte2' inside non-recursive 'cte1'",
      "set tidb_opt_force_inline_cte=0; -- disable force inline CTE",
      "with cte as (select * from t) select * from cte; -- inlined by single consumer",
      "with cte as (select /*+ MERGE() */ * from t) select * from cte; -- inline, merge hint override session variable",
      "with recursive cte1(c1) as (select 1 union select /*+ MERGE() */ c1 + 1 c1 from cte1 where c1 < 100) select * from cte1; -- Recursive CTE can not be inlined",
      "with cte1 as (with cte2 as (select * from t) select * from cte2) select * from cte1; -- non-recursive 'cte2' definition inside another non-recursive 'cte1'",
      "with recursive cte2(c1) as (with cte1 as (select * from t) select a c1 from cte1 union select c1+1 c1 from cte2 where c1 < 100) select * from cte2; -- non-recursive 'cte1' inside recursive 'cte2'",
      "with cte1 as (with recursive cte2(c1) as (select 1 union select c1 + 1 c1 from cte2 where c1 < 100) select * from cte2) select * from cte1; -- recursive 'cte2' inside non-recursive 'cte1'"
    ]
  },
  {
    "name": "TestSingleConsumerCTE",
    "cases": [
      "with cte as (select 1) select * from cte; -- inline cte",
      "with cte1 as (select 1), cte2 as (select 2) select * from cte1 union select * from cte2; -- inline cte1, cte2",
      "with cte as (select 1) select * from cte union select * from cte; -- cannot be inlined",
      "with cte as (with cte as (select 1) select * from cte) select * from cte; -- inline nested cte",
      "with cte as (with cte as (select 1) select * from cte) select * from cte a, cte b; -- inline inner cte, cannot be inlined outer cte",
      "with cte1 as (select 1), cte2 as (with cte3 as (select * from cte1) select * from cte3) select * from cte1, cte2; -- inline cte2, cte3, cannot be inlined cte1",
      "with cte1 as (select 1), cte2 as (with cte3 as (select * from cte1) select * from cte3) select * from cte2; -- inline cte1, cte2, cte3",
      "with cte1 as (select 1), cte2 as (select * from cte1) select * from cte2 a, cte2 b; -- inline cte1, cannot be inlined cte2",
      "with recursive cte(a) as (select 1 union select a from cte) select * from cte; -- recursive cte cannot be inlined",
      "with x as (select * from (select a from t for update) s) select * from x where a = 1;",
      "set tidb_opt_force_inline_cte=1; -- enable force inline CTE",
      "with cte as (select 1) select * from cte union select * from cte; -- force inline cte while multi-consumer",
      "set tidb_opt_force_inline_cte=0; -- disable force inline CTE",
      "with cte as (select 1) select /*+ MERGE() */ * from cte union select * from cte; -- firstly inline cte, secondly cannot be inlined"
    ]
  },
  {
    "name": "TestPushdownDistinctEnable",
    "cases": [
      "select /*+ HASH_AGG() */ avg(distinct a) from t;", // InjectProjBelowAgg
      "select /*+ HASH_AGG() */ a, count(distinct a) from t;", // firstrow(a) cannot be removed.
      "select /*+ HASH_AGG() */ avg(b), c, avg(b), count(distinct A, B),  count(distinct A), count(distinct c), sum(b) from t group by c;",
      "select /*+ STREAM_AGG() */ count(distinct c) from t group by c;", // can push down
      "select /*+ STREAM_AGG() */ count(distinct c) from t;", // can not push down because c is not in group by
      "select /*+ HASH_AGG() */ count(distinct c) from t;", // can push down
      "select count(distinct c) from t group by c;",
      "select count(distinct c) from t;", // should not use streamAgg because c is not in group by

      "select /*+ HASH_AGG(), AGG_TO_COP() */ sum(distinct b) from pt;",
      "select /*+ HASH_AGG(), AGG_TO_COP() */ count(distinct a) from (select * from ta union all select * from tb) t;",

      "select distinct DATE_FORMAT(timestamp, '%Y-%m-%d %H') as tt from tc ;"
    ]
  },
  {
    "name": "TestPushdownDistinctDisable",
    "cases": [
      // do not pushdown even AGG_TO_COP is specified.
      "select /*+ HASH_AGG(), AGG_TO_COP() */ avg(distinct a) from t;",
      "select /*+ HASH_AGG(), AGG_TO_COP() */ a, count(distinct a) from t;",
      "select /*+ HASH_AGG(), AGG_TO_COP() */ avg(b), c, avg(b), count(distinct A, B),  count(distinct A), count(distinct c), sum(b) from t group by c;",
      "select /*+ STREAM_AGG(), AGG_TO_COP() */ count(distinct c) from t group by c;",
      "select /*+ STREAM_AGG(), AGG_TO_COP() */ count(distinct c) from t;",
      "select /*+ HASH_AGG(), AGG_TO_COP() */ count(distinct c) from t;",
      "select /*+ AGG_TO_COP() */ count(distinct c) from t group by c;",

      "select /*+ HASH_AGG(), AGG_TO_COP() */ sum(distinct b) from pt;",
      "select /*+ HASH_AGG(), AGG_TO_COP() */ count(distinct a) from (select * from ta union all select * from tb) t;"
    ]
  },
  {
    "name": "TestPushdownDistinctEnableAggPushDownDisable",
    "cases": [
      "select /*+ HASH_AGG(), AGG_TO_COP() */ sum(distinct b) from pt;",
      "select /*+ HASH_AGG(), AGG_TO_COP() */ count(distinct a) from (select * from ta union all select * from tb) t;",
      "select distinct DATE_FORMAT(timestamp, '%Y-%m-%d %H') as tt from tc ;"
    ]
  },
  {
    "name": "TestGroupConcatOrderby",
    "cases": [
      "select /*+ agg_to_cop */ group_concat(name ORDER BY name desc SEPARATOR '++'), group_concat(id ORDER BY name desc, id asc SEPARATOR '--') from test;",
      "select /*+ agg_to_cop */ group_concat(name ORDER BY name desc SEPARATOR '++'), group_concat(id ORDER BY name desc, id asc SEPARATOR '--') from ptest;",
      "select /*+ agg_to_cop */ group_concat(distinct name order by name desc) from test;",
      "select /*+ agg_to_cop */ group_concat(distinct name order by name desc) from ptest;"
    ]
  },
  {
    "name": "TestDAGPlanBuilderWindow",
    "cases":[
      "select lead(a, 1) over (partition by null) as c from t"
    ]
  },
  {
    "name": "TestDAGPlanBuilderWindowParallel",
    "cases":[
      "select lead(a, 1) over (partition by null) as c from t",
      "select lead(a, 1) over (partition by b) as c from t"
    ]
  },
  {
    "name": "TestNominalSort",
    "cases": [
      "select /*+ TIDB_SMJ(t1, t2) */ t1.a from t t1, t t2 where t1.a = t2.b order by t1.a",
      "select /*+ TIDB_SMJ(t1, t2) */ t1.a from t t1, t t2 where t1.a = t2.b order by t1.a+1",
      "select /*+ TIDB_SMJ(t1, t2) */ t1.a from t t1, t t2 where t1.a = t2.b order by t1.a-1",
      "select /*+ TIDB_SMJ(t1, t2) */ t1.a from t t1, t t2 where t1.a = t2.b order by -t1.a",
      "select /*+ TIDB_SMJ(t1, t2) */ t1.a from t t1, t t2 where t1.a = t2.b order by -t1.a+3",
      "select /*+ TIDB_SMJ(t1, t2) */ t1.a from t t1, t t2 where t1.a = t2.b order by 1+t1.a",
      "select /*+ TIDB_SMJ(t1, t2) */ t1.a from t t1, t t2 where t1.a = t2.b order by 1-t1.a",
      "select /*+ TIDB_SMJ(t1, t2) */ t1.a from t t1, t t2 where t1.a = t2.b order by 1-t1.a+3",
      "select /*+ TIDB_SMJ(t1, t2) */ t1.a from t t1, t t2 where t1.a = t2.b order by 1+t1.a+3",
      "select /*+ TIDB_SMJ(t1, t2) */ t1.a from t t1, t t2 where t1.a = t2.b order by 3*t1.a"
    ]
  },
  {
    "name": "TestInlineProjection",
    "cases":[
      "select /*+ HASH_JOIN(t1) */ t1.b, t2.b from t1, t2 where t1.a = t2.a;",
      "select /*+ HASH_JOIN(t1) */ t1.b, t2.b from t1 inner join t2 on t1.a = t2.a;",
      "select /*+ HASH_JOIN(t1) */ t1.b, t2.b from t1 left outer join t2 on t1.a = t2.a;",
      "select /*+ HASH_JOIN(t1) */ t1.b, t2.b from t1 right outer join t2 on t1.a = t2.a;",
      "select 1 from (select /*+ HASH_JOIN(t1) */ t1.a in (select t2.a from t2) from t1) x;",
      "select 1 from (select /*+ HASH_JOIN(t1) */ t1.a not in (select t2.a from t2) from t1) x;",
      "select /*+ INL_JOIN(t1) */ t1.b, t2.b from t1 inner join t2 on t1.a = t2.a;",
      "select /*+ INL_HASH_JOIN(t1) */ t1.b, t2.b from t1 inner join t2 on t1.a = t2.a;",
      "select /*+ INL_MERGE_JOIN(t1) */ t1.b, t2.b from t1 inner join t2 on t1.a = t2.a;",
      "select /*+ MERGE_JOIN(t1) */ t1.b, t2.b from t1 inner join t2 on t1.a = t2.a;"
    ]
  },
  {
    "name": "TestHintFromDiffDatabase",
    "cases": [
      "select /*+ inl_hash_join(test.t1) */ * from test.t2 join test.t1 on test.t2.a = test.t1.a"
    ]
  },
  {
    "name": "TestNthPlanHintWithExplain",
    "cases": [
      "select /*+nth_plan(1)*/ * from test.tt where a=1 and b=1",
      "select /*+nth_plan(2)*/ * from test.tt where a=1 and b=1;",
      "select /*+nth_plan(3)*/ * from test.tt where a=1 and b=1;",
      "select /*+nth_plan(2)*/ * from test.tt where a=1 and b=1;",
      "select * from test.tt where a=1 and b=1"
    ]
  },
  {
    "name": "TestINMJHint",
    "cases": [
      "select /*+ inl_merge_join(t2) */ t1.a, t2.a from t1 left join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ inl_hash_join(t2) */ t1.a, t2.a from t1 left join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ inl_join(t2) */ t1.a, t2.a from t1 left join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join(t2) */ t1.a, t2.a from t1 left join t2 on t1.a=t2.a and t1.b=t2.b"
    ]
  },
  {
    "name": "TestEliminateMaxOneRow",
    "cases": [
      "select a from t2 where t2.a < (select t1.a from t1 where t1.a = t2.a);",
      "select a from t2 where t2.a < (select t1.a from t1 where t1.b = t2.b and t1.a is null);",
      "select a from t2 where t2.a < (select t3.a from t3 where t3.a = t2.a);"
    ]
  },
  {
    "name": "TestEnumIndex",
    "cases": [
      "select e from t where e = 'b'",
      "select e from t where e != 'b'",
      "select e from t where e > 'b'",
      "select e from t where e >= 'b'",
      "select e from t where e < 'b'",
      "select e from t where e <= 'b'",
      "select e from t where e = 2",
      "select e from t where e != 2",
      "select e from t where e > 2",
      "select e from t where e >= 2",
      "select e from t where e < 2",
      "select e from t where e <= 2",

      // Out of range
      "select e from t where e > ''",
      "select e from t where e > 'd'",
      "select e from t where e > -1",
      "select e from t where e > 5",

      // zero-value
      "select e from t where e = ''",
      "select e from t where e != ''"
    ]
  },
  {
    "name": "TestIssue27233",
    "cases": [
      "SELECT col2 FROM PK_S_MULTI_31 AS T1 WHERE (SELECT count(DISTINCT COL1, COL2) FROM PK_S_MULTI_31 AS T2 WHERE T2.COL1>T1.COL1)>2 order by col2;"
    ]
  },
  {
    "name": "TestSelectionPartialPushDown",
    "cases": [
      // Make sure row_count(tikv_selection) == row_count(table_reader) and row_count(table_reader) > row_count(tidb_selection)
      "select * from t1 where a > 1 and b > 1",
      // Make sure row_count(tikv_selection) == row_count(index_lookup) and row_count(index_lookup) > row_count(tidb_selection)
      "select * from t2 use index(idx_a) where a > 1 and b > 1 and c > 1"
    ]
  },
  {
    "name": "TestIssue28316",
    "cases": [
      "select * from t where t.a < 3 and t.a < 3"
    ]
  },
  {
    "name": "TestSkewDistinctAgg",
    "cases": [
      "select date_format(d,'%Y') as df, sum(a), count(b), count(distinct c) from t group by date_format(d,'%Y')",
      "select d, a, count(*), count(b), count(distinct c) from t group by d, a",
      "select d, sum(a), count(b), avg(distinct c) from t group by d"
    ]
  },
  {
    "name": "TestMPPSinglePartitionType",
    "cases": [
      "select * from employee where deptid>1",
      "select deptid+5, empid*10  from employee where deptid>1",
      // test normal aggregation, MPP2Phase.
      "select count(*) from employee group by deptid+1",
      // test normal aggregation, MPPScalar.
      "select count(distinct deptid) a from employee",
      // test normal join, Broadcast.
      "select * from employee join employee e1 using(deptid)",
      // test redundant collect exchange can be eliminated.
      "select count(distinct a) from (select count(distinct deptid) a from employee) x",
      // test mppScalar agg below mpp2Phase agg.
      "select count(a) from (select count(distinct deptid) a, count(distinct empid) b from employee) x group by b+1",
      // test mppScalar agg below mpp1Phase agg, TODO: add hint to enforce
      // test mppScalar agg below mppTiDB agg, TODO: add hint to enforce
      "select count(a) from (select count(distinct deptid) a, count(distinct empid) b from employee) x group by b",
      // test mppScalar agg below join
      "select * from employee join (select count(distinct deptid) a, count(distinct empid) b from employee) e1",
      "select * from employee e1 join (select count(distinct deptid) a from employee) e2 on e1.deptid = e2.a",
      "select * from (select count(distinct deptid) a from employee) e1 join employee e2 on e1.a = e2.deptid",
      "select * from (select count(distinct deptid) a from employee) e1 join (select count(distinct deptid) b from employee) e2 on e1.a=e2.b",
      // test mpp2Phase agg below join
      "select * from employee e1 join employee e2 on e1.deptid = e2.deptid",
      "select * from (select deptid+1 d, count(empid) a from employee group by d) e1 join employee e2 on e1.d = e2.deptid",
      "select * from employee e1 join (select deptid+1 d, count(empid) a from employee group by d) e2 on e1.deptid = e2.d",
      "select * from (select deptid+1 d, count(empid) a from employee group by d) e1 join (select deptid+1 d, count(empid) a from employee group by d) e2 on e1.d = e2.d",
      // non-broadcast join
      "set tidb_broadcast_join_threshold_count=1",
      "set tidb_broadcast_join_threshold_size=1",
      "select * from (select count(distinct deptid) a from employee) e1 join employee e2 on e1.a = e2.deptid",
      "select * from (select count(distinct deptid) a from employee) e1 join (select count(distinct deptid) b from employee) e2 on e1.a=e2.b",
      "select * from employee e1 join employee e2 on e1.deptid = e2.deptid",
      "select * from (select deptid+1 d, count(empid) a from employee group by d) e1 join employee e2 on e1.d = e2.deptid",
      "select * from employee e1 join (select deptid+1 d, count(empid) a from employee group by d) e2 on e1.deptid = e2.d",
      "select * from (select deptid+1 d, count(empid) a from employee group by d) e1 join (select deptid+1 d, count(empid) a from employee group by d) e2 on e1.d = e2.d"
    ]
  },
  {
    "name": "TestSemiJoinRewriteHints",
    "cases": [
      "select /*+ SEMI_JOIN_REWRITE() */ * from t",
      "select * from t where a > (select /*+ SEMI_JOIN_REWRITE() */ min(b) from t t1 where t1.c = t.c)",
      "select * from t where exists (select /*+ SEMI_JOIN_REWRITE() */ 1 from t t1 where t1.a=t.a)",
      "select * from t where exists (select /*+ SEMI_JOIN_REWRITE() */ t.b from t t1 where t1.a=t.a)",
      "select exists(select /*+ SEMI_JOIN_REWRITE() */ * from t t1 where t1.a=t.a) from t",
      "select * from t where exists (select /*+ SEMI_JOIN_REWRITE() */ 1 from t t1 where t1.a > t.a)"
    ]
  },
  {
    "name": "TestHJBuildAndProbeHint",
    "cases": [
      // Test for different join type
      // inner join
      "select /*+ hash_join_build(t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_build(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",

      "select /*+ hash_join_build(t2), hash_join_probe(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t2), hash_join_build(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",

      // outer join
      "select /*+ hash_join_build(t2) */ t1.a, t2.a from t1 left join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t2) */ t1.a, t2.a from t1 left join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_build(t1) */ t1.a, t2.a from t1 left join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t1) */ t1.a, t2.a from t1 left join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_build(t2) */ t1.a, t2.a from t1 right join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t2) */ t1.a, t2.a from t1 right join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_build(t1) */ t1.a, t2.a from t1 right join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t1) */ t1.a, t2.a from t1 right join t2 on t1.a=t2.a and t1.b=t2.b",

      // straight_join
      "select /*+ hash_join_build(t2) */ t1.a, t2.a from t1 straight_join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t2) */ t1.a, t2.a from t1 straight_join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_build(t1) */ t1.a, t2.a from t1 straight_join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t1) */ t1.a, t2.a from t1 straight_join t2 on t1.a=t2.a and t1.b=t2.b",

      // cross join
      "select /*+ hash_join_build(t2) */ t1.a, t2.a from t1 cross join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t2) */ t1.a, t2.a from t1 cross join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_build(t1) */ t1.a, t2.a from t1 cross join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t1) */ t1.a, t2.a from t1 cross join t2 on t1.a=t2.a and t1.b=t2.b",

      // semi join
      "select /*+ hash_join_build(t1) */ * from t1 where t1.a in (select t2.a from t2 where t1.b = t2.b)",
      "select /*+ hash_join_probe(t1) */ * from t1 where t1.a in (select t2.a from t2 where t1.b = t2.b)",
      "select /*+ hash_join_build(t2@sel_2) */ * from t1 where t1.a in (select t2.a from t2 where t1.b = t2.b)",
      "select /*+ hash_join_probe(t2@sel_2) */ * from t1 where t1.a in (select t2.a from t2 where t1.b = t2.b)",

      // anti semi join
      "select /*+ hash_join_build(t1) */ * from t1 where t1.a not in (select t2.a from t2 where t1.b = t2.b)",
      "select /*+ hash_join_probe(t1) */ * from t1 where t1.a not in (select t2.a from t2 where t1.b = t2.b)",
      "select /*+ hash_join_build(t2@sel_2) */ * from t1 where t1.a not in (select t2.a from t2 where t1.b = t2.b)",
      "select /*+ hash_join_probe(t2@sel_2) */ * from t1 where t1.a not in (select t2.a from t2 where t1.b = t2.b)",

      // left outer semi join
      "select /*+ hash_join_build(t1) */ sum(t1.a in (select a from t2)) from t1",
      "select /*+ hash_join_probe(t1) */ sum(t1.a in (select a from t2)) from t1",
      "select /*+ hash_join_build(t2@sel_2) */ sum(t1.a in (select a from t2)) from t1",
      "select /*+ hash_join_probe(t2@sel_2) */ sum(t1.a in (select a from t2)) from t1",

      // anti left outer semi join
      "select /*+ hash_join_build(t1) */ sum(t1.a not in (select a from t2)) from t1",
      "select /*+ hash_join_probe(t1) */ sum(t1.a not in (select a from t2)) from t1",
      "select /*+ hash_join_build(t2@sel_2) */ sum(t1.a not in (select a from t2)) from t1",
      "select /*+ hash_join_probe(t2@sel_2) */ sum(t1.a not in (select a from t2)) from t1",

      // Hint scope
      // The same table name appear in the hint
      "select /*+ hash_join_probe(t2, t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_build(t1, t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",

      // The undefined table name appear in the hint
      "select /*+ hash_join_probe(tt) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_build(tt) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",

      // The alias appear in the hint
      "select /*+ hash_join_probe(tt) */ tt.a, t2.a from t1 as tt join t2 on tt.a=t2.a and tt.b=t2.b",
      "select /*+ hash_join_build(tt) */ tt.a, t2.a from t1 as tt join t2 on tt.a=t2.a and tt.b=t2.b",

      // The hints are conflict
      "select /*+ hash_join_probe(t2, t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_build(t1, t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_build(t1) hash_join_probe(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_build(t2) hash_join_probe(t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",

      // Combine with other hints
      "select /*+ hash_join_build(t1) leading(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b join t3 on t2.a = t3.a",
      "select /*+ hash_join_build(t1) leading(t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b join t3 on t2.a = t3.a",
      "select /*+ hash_join_probe(t1) leading(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b join t3 on t2.a = t3.a",
      "select /*+ hash_join_probe(t1) leading(t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b join t3 on t2.a = t3.a",

      "select /*+ hash_join_build(t1) straight_join() */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b join t3 on t2.a = t3.a",
      "select /*+ hash_join_build(t1) straight_join() */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b join t3 on t2.a = t3.a",
      "select /*+ hash_join_probe(t1) straight_join() */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b join t3 on t2.a = t3.a",
      "select /*+ hash_join_probe(t1) straight_join() */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b join t3 on t2.a = t3.a",

      "select /*+ hash_join_build(t2) hash_join(t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t2) hash_join(t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_build(t2) hash_join(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t2) hash_join(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_build(t2) hash_join(t2, t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t2) hash_join(t2, t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",

      "select /*+ hash_join_build(t2) INL_JOIN(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t2) INL_JOIN(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_build(t1) INL_JOIN(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t1) INL_JOIN(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",

      "select /*+ hash_join_build(t2) INL_HASH_JOIN(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t2) INL_HASH_JOIN(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_build(t1) INL_HASH_JOIN(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t1) INL_HASH_JOIN(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",

      "select /*+ hash_join_build(t2) merge_join(t1, t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t2) merge_join(t1, t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_build(t1) merge_join(t1, t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t1) merge_join(t1, t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",

      "SELECT * FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.a = t1.a);",
      "SELECT /*+ hash_join_probe(t1) */ * FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.a = t1.a);",
      "SELECT /*+ hash_join_probe(t2@sel_2) */ * FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.a = t1.a);",
      "SELECT /*+ hash_join_probe(t1) */ * FROM t1 WHERE EXISTS (SELECT /*+ SEMI_JOIN_REWRITE() */ 1 FROM t2 WHERE t2.a = t1.a);",
      "SELECT /*+ hash_join_probe(t2@sel_2) */ * FROM t1 WHERE EXISTS (SELECT /*+ SEMI_JOIN_REWRITE() */ 1 FROM t2 WHERE t2.a = t1.a);",
      "SELECT /*+ hash_join_build(t1) */ * FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.a = t1.a);",
      "SELECT /*+ hash_join_build(t2@sel_2) */ * FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.a = t1.a);",
      "SELECT /*+ hash_join_build(t1) */ * FROM t1 WHERE EXISTS (SELECT /*+ SEMI_JOIN_REWRITE() */ 1 FROM t2 WHERE t2.a = t1.a);",
      "SELECT /*+ hash_join_build(t2@sel_2) */ * FROM t1 WHERE EXISTS (SELECT /*+ SEMI_JOIN_REWRITE() */ 1 FROM t2 WHERE t2.a = t1.a);",

      "SELECT t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);",
      "SELECT /*+ hash_join_build(t1) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);",
      "SELECT /*+ hash_join_probe(t1) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);",
      "SELECT /*+ hash_join_build(t2@sel_2) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);",
      "SELECT /*+ hash_join_probe(t2@sel_2) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);",
      "SELECT /*+ USE_TOJA(TRUE) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);",
      "SELECT /*+ USE_TOJA(TRUE) hash_join_build(t1) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);",
      "SELECT /*+ USE_TOJA(TRUE) hash_join_probe(t1) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);",
      "SELECT /*+ USE_TOJA(TRUE) hash_join_build(t2@sel_2) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);",
      "SELECT /*+ USE_TOJA(TRUE) hash_join_probe(t2@sel_2) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);",
      "SELECT /*+ USE_TOJA(false) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);",
      "SELECT /*+ USE_TOJA(false) hash_join_build(t1) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);",
      "SELECT /*+ USE_TOJA(false) hash_join_probe(t1) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);",
      "SELECT /*+ USE_TOJA(false) hash_join_build(t2@sel_2) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);",
      "SELECT /*+ USE_TOJA(false) hash_join_probe(t2@sel_2) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);"
    ]
  },
  {
    "name": "TestHJBuildAndProbeHint4StaticPartitionTable",
    "cases": [
      "select /*+ hash_join_build(t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_build(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b"
    ]
  },
  {
    "name": "TestHJBuildAndProbeHint4DynamicPartitionTable",
    "cases": [
      "select /*+ hash_join_build(t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_build(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b"
    ]
  },
  {
    "name": "TestHJBuildAndProbeHint4TiFlash",
    "cases": [
      "select /*+ hash_join_build(t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_build(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
      "select /*+ hash_join_probe(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b"
    ]
  },
  {
    "name": "TestNoDecorrelateHint",
    "cases": [
      "select /*+ no_decorrelate() */ * from t1",
      "select * from t1, (select /*+ no_decorrelate() */ * from t2) n",
      "select a+1, b-1 from (select /*+ no_decorrelate() */ * from t1) n",
      "select exists (select /*+ semi_join_rewrite(), no_decorrelate() */ * from t1 where t1.a=t3.a) from t3",

      "select t1.a from t1 where t1.a in (select t2.b from t2 where t2.a = t1.b)",
      "select t1.a from t1 where t1.a in (select /*+ no_decorrelate() */ t2.b from t2 where t2.a = t1.b)",

      "select t1.a from t1 where t1.a = any (select t2.b from t2 where t2.a = t1.b)",
      "select t1.a from t1 where t1.a = any (select /*+ no_decorrelate() */ t2.b from t2 where t2.a = t1.b)",

      "select t1.a, t1.a != any (select t2.b from t2 where t2.a = t1.b) from t1",
      "select t1.a, t1.a != any (select /*+ no_decorrelate() */ t2.b from t2 where t2.a = t1.b) from t1",

      "select t1.a, t1.a > all (select t2.b from t2 where t2.a = t1.b) from t1",
      "select t1.a, t1.a > all (select /*+ no_decorrelate() */ t2.b from t2 where t2.a = t1.b) from t1",

      "select t1.a, (select t2.b from t2 where t2.a = t1.b) from t1",
      "select t1.a, (select /*+ no_decorrelate() */ t2.b from t2 where t2.a = t1.b) from t1",

      "select t1.a, t1.b not in (select t3.b from t3) from t1",
      "select t1.a, t1.b not in (select /*+ no_decorrelate() */ t3.b from t3) from t1",

      "select exists (select t3.b from t3 where t3.a = t1.b limit 2) from t1",
      "select exists (select /*+ no_decorrelate() */ t3.b from t3 where t3.a = t1.b limit 2) from t1",

      "select t1.a, (select sum(t1.a) from t2 where t2.a = 10) from t1",
      "select t1.a, (select /*+ no_decorrelate() */ sum(t1.a) from t2 where t2.a = 10) from t1",

      "select (select count(t3.a) from t3 where t3.b = t1.b) from t1;",
      "select (select /*+ no_decorrelate() */ count(t3.a) from t3 where t3.b = t1.b) from t1;",

      "SELECT ta.NAME,(SELECT sum(tb.CODE) FROM tb WHERE ta.id = tb.id) tb_sum_code FROM ta WHERE ta.NAME LIKE 'chad999%'",
      "SELECT ta.NAME,(SELECT /*+ no_decorrelate() */ sum(tb.CODE) FROM tb WHERE ta.id = tb.id) tb_sum_code FROM ta WHERE ta.NAME LIKE 'chad999%'",

      "SELECT ta.NAME,(SELECT sum(tb.CODE) FROM tb WHERE ta.id = tb.id and exists (select 1 from tc where tb.name=tc.name and tc.`code` like '999%')) tb_sum_code FROM ta WHERE ta.NAME LIKE 'chad999%'",
      "SELECT ta.NAME,(SELECT /*+ no_decorrelate() */ sum(tb.CODE) FROM tb WHERE ta.id = tb.id and exists (select 1 from tc where tb.name=tc.name and tc.`code` like '999%')) tb_sum_code FROM ta WHERE ta.NAME LIKE 'chad999%'",
      "SELECT ta.NAME,(SELECT sum(tb.CODE) FROM tb WHERE ta.id = tb.id and exists (select /*+ no_decorrelate() */ 1 from tc where tb.name=tc.name and tc.`code` like '999%')) tb_sum_code FROM ta WHERE ta.NAME LIKE 'chad999%'",
      "SELECT ta.NAME,(SELECT /*+ no_decorrelate() */ sum(tb.CODE) FROM tb WHERE ta.id = tb.id and exists (select /*+ no_decorrelate() */ 1 from tc where tb.name=tc.name and tc.`code` like '999%')) tb_sum_code FROM ta WHERE ta.NAME LIKE 'chad999%'",

      "SELECT ta.id, 'split' as flag FROM ta WHERE ta.NAME ='chad999' and (select max(tb.code) from tb where ta.id=tb.id ) > 900",
      "SELECT ta.id, 'split' as flag FROM ta WHERE ta.NAME ='chad999' and (select /*+ no_decorrelate() */ max(tb.code) from tb where ta.id=tb.id ) > 900",

      "SELECT ta.NAME FROM ta WHERE EXISTS (select 1 from tb where ta.code = tb.code and tb.NAME LIKE 'chad9%') AND (select max(id) from tc where ta.name=tc.name and tc.name like 'chad99%') > 100 and (select max(id) from td where ta.id=td.id and td.name like 'chad999%') > 100",
      "SELECT ta.NAME FROM ta WHERE EXISTS (select /*+ semi_join_rewrite() */ 1 from tb where ta.code = tb.code and tb.NAME LIKE 'chad9%') AND (select /*+ no_decorrelate() */ max(id) from tc where ta.name=tc.name and tc.name like 'chad99%') > 100 and (select /*+ no_decorrelate() */ max(id) from td where ta.id=td.id and td.name like 'chad999%') > 100",
      "SELECT ta.NAME FROM ta WHERE EXISTS (select /*+ no_decorrelate() */ 1 from tb where ta.code = tb.code and tb.NAME LIKE 'chad9%') AND (select /*+ no_decorrelate() */ max(id) from tc where ta.name=tc.name and tc.name like 'chad99%') > 100 and (select /*+ no_decorrelate() */ max(id) from td where ta.id=td.id and td.name like 'chad999%') > 100"

    ]
  },
  {
    "name": "TestCountStarForTikv",
    "cases": [
      "select count(*) from t",
      "select count(1), count(3.1415), count(0), count(null) from t -- shouldn't be rewritten",
      "select count(*) from t where a=1",
      "select count(*) from t_pick_row_id",
      "select t.b, t.c from (select count(*) as c from t) a, t where a.c=t.a -- shouldn't be rewritten",
      "select * from t out1 where out1.a > (select count(*) from t inn where inn.a = out1.b) -- shouldn't be rewritten",
      "select count(*) from t t1, t t2 where t1.a=t2.e -- shouldn't be rewritten",
      "select count(distinct 1) from t -- shouldn't be rewritten",
      "select count(1), count(a), count(b) from t -- shouldn't be rewritten",
      "select a, count(*) from t group by a -- shouldn't be rewritten",
      "select sum(a) from t -- sum shouldn't be rewritten"
    ]
  },
  {
    "name": "TestCountStarForTiFlash",
    "cases": [
      "select count(*) from t",
      "select count(1), count(3.1415), count(0), count(null) from t -- every count but count(null) can be rewritten",
      "select count(*) from t where a=1",
      "select count(*) from t_pick_row_id",
      "select t.b, t.c from (select count(*) as c from t) a, t where a.c=t.a -- test recursive",
      "select * from t out1 where out1.a > (select count(*) from t inn where inn.a = out1.b) -- shouldn't be rewritten for correlated sub query",
      "select count(*) from t t1, t t2 where t1.a=t2.e -- shouldn't be rewritten when join under agg",
      "select count(distinct 1) from t -- shouldn't be rewritten",
      "select count(1), count(a), count(b) from t -- keep count(1)",
      "select a, count(*) from t group by a -- shouldn't be rewritten",
      "select sum(a) from t -- sum shouldn't be rewritten"
    ]
  }
]
