[
  {
    "Name": "TestMPPHints",
    "Cases": [
      {
        "SQL": "select /*+ read_from_storage(tiflash[t]), MPP_1PHASE_AGG() */ a, sum(b) from t group by a, c",
        "Plan": [
          "TableReader 8000.00 root  data:ExchangeSender",
          "└─ExchangeSender 8000.00 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─Projection 8000.00 mpp[tiflash]  test.t.a, Column#5",
          "    └─Projection 8000.00 mpp[tiflash]  Column#5, test.t.a",
          "      └─HashAgg 8000.00 mpp[tiflash]  group by:Column#10, Column#11, funcs:sum(Column#8)->Column#5, funcs:firstrow(Column#9)->test.t.a",
          "        └─Projection 10000.00 mpp[tiflash]  cast(test.t.b, decimal(10,0) BINARY)->Column#8, test.t.a, test.t.a, test.t.c",
          "          └─ExchangeReceiver 10000.00 mpp[tiflash]  ",
          "            └─ExchangeSender 10000.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: test.t.a, collate: binary], [name: test.t.c, collate: binary]",
          "              └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select /*+ read_from_storage(tiflash[t]), MPP_2PHASE_AGG() */ a, sum(b) from t group by a, c",
        "Plan": [
          "TableReader 8000.00 root  data:ExchangeSender",
          "└─ExchangeSender 8000.00 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─Projection 8000.00 mpp[tiflash]  test.t.a, Column#5",
          "    └─Projection 8000.00 mpp[tiflash]  Column#5, test.t.a",
          "      └─HashAgg 8000.00 mpp[tiflash]  group by:test.t.a, test.t.c, funcs:sum(Column#10)->Column#5, funcs:firstrow(test.t.a)->test.t.a",
          "        └─ExchangeReceiver 8000.00 mpp[tiflash]  ",
          "          └─ExchangeSender 8000.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: test.t.a, collate: binary], [name: test.t.c, collate: binary]",
          "            └─HashAgg 8000.00 mpp[tiflash]  group by:Column#13, Column#14, funcs:sum(Column#12)->Column#10",
          "              └─Projection 10000.00 mpp[tiflash]  cast(test.t.b, decimal(10,0) BINARY)->Column#12, test.t.a, test.t.c",
          "                └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), shuffle_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a",
        "Plan": [
          "TableReader 12487.50 root  data:ExchangeSender",
          "└─ExchangeSender 12487.50 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─HashJoin 12487.50 mpp[tiflash]  inner join, equal:[eq(test.t.a, test.t.a)]",
          "    ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash]  ",
          "    │ └─ExchangeSender 9990.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: test.t.a, collate: binary]",
          "    │   └─Selection 9990.00 mpp[tiflash]  not(isnull(test.t.a))",
          "    │     └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo",
          "    └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash]  ",
          "      └─ExchangeSender 9990.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: test.t.a, collate: binary]",
          "        └─Selection 9990.00 mpp[tiflash]  not(isnull(test.t.a))",
          "          └─TableFullScan 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), broadcast_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a",
        "Plan": [
          "TableReader 12487.50 root  data:ExchangeSender",
          "└─ExchangeSender 12487.50 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─HashJoin 12487.50 mpp[tiflash]  inner join, equal:[eq(test.t.a, test.t.a)]",
          "    ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash]  ",
          "    │ └─ExchangeSender 9990.00 mpp[tiflash]  ExchangeType: Broadcast",
          "    │   └─Selection 9990.00 mpp[tiflash]  not(isnull(test.t.a))",
          "    │     └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo",
          "    └─Selection(Probe) 9990.00 mpp[tiflash]  not(isnull(test.t.a))",
          "      └─TableFullScan 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo"
        ]
      }
    ]
  },
  {
    "Name": "TestHintScope",
    "Cases": [
      {
        "SQL": "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",
        "Best": "MergeInnerJoin{TableReader(Table(t))->IndexJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,NULL]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)"
      },
      {
        "SQL": "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",
        "Best": "MergeInnerJoin{TableReader(Table(t))->IndexJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,NULL]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)"
      },
      {
        "SQL": "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",
        "Best": "MergeInnerJoin{TableReader(Table(t))->LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)->Sort}(test.t.a,test.t.a)"
      },
      {
        "SQL": "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",
        "Best": "IndexJoin{TableReader(Table(t))->LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)"
      },
      {
        "SQL": "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",
        "Best": "IndexJoin{TableReader(Table(t))->LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)"
      },
      {
        "SQL": "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",
        "Best": "IndexJoin{TableReader(Table(t))->MergeInnerJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)"
      },
      {
        "SQL": "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",
        "Best": "RightHashJoin{TableReader(Table(t))->MergeInnerJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)"
      },
      {
        "SQL": "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",
        "Best": "RightHashJoin{TableReader(Table(t))->MergeInnerJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)"
      },
      {
        "SQL": "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",
        "Best": "RightHashJoin{TableReader(Table(t))->IndexJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.c,test.t.a)}(test.t.a,test.t.a)"
      },
      {
        "SQL": "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",
        "Best": "MergeInnerJoin{TableReader(Table(t))->MergeInnerJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)"
      },
      {
        "SQL": "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",
        "Best": "IndexJoin{TableReader(Table(t))->MergeInnerJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)"
      },
      {
        "SQL": "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",
        "Best": "RightHashJoin{TableReader(Table(t))->MergeInnerJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)"
      },
      {
        "SQL": "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",
        "Best": "MergeInnerJoin{LeftHashJoin{TableReader(Table(t))->IndexReader(Index(t.f)[[NULL,+inf]])}(test.t.a,test.t.a)->Sort->TableReader(Table(t))->Sort}(test.t.b,test.t.b)"
      },
      {
        "SQL": "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",
        "Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->TableReader(Table(t))}(test.t.a,test.t.b)->Projection->HashAgg->Sort->StreamAgg->Projection"
      },
      {
        "SQL": "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",
        "Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->TableReader(Table(t))}(test.t.a,test.t.b)->Sort->Projection->StreamAgg->HashAgg->Projection"
      },
      {
        "SQL": "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",
        "Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->TableReader(Table(t))}(test.t.a,test.t.b)->Projection->HashAgg->HashAgg->Projection"
      },
      {
        "SQL": "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",
        "Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->TableReader(Table(t))}(test.t.a,test.t.b)->Projection->HashAgg->Sort->StreamAgg->Projection"
      }
    ]
  },
  {
    "Name": "TestIndexHint",
    "Cases": [
      {
        "SQL": "select /*+ USE_INDEX(t, c_d_e) */ * from t",
        "Best": "IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))",
        "HasWarn": false,
        "Hints": "use_index(@`sel_1` `test`.`t` `c_d_e`)"
      },
      {
        "SQL": "select /*+ USE_INDEX(test.t, c_d_e) */ * from t",
        "Best": "IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))",
        "HasWarn": false,
        "Hints": "use_index(@`sel_1` `test`.`t` `c_d_e`)"
      },
      {
        "SQL": "select /*+ IGNORE_INDEX(t, c_d_e) */ c from t order by c",
        "Best": "TableReader(Table(t))->Sort",
        "HasWarn": false,
        "Hints": "use_index(@`sel_1` `test`.`t` )"
      },
      {
        "SQL": "select /*+ IGNORE_INDEX(test.t, c_d_e) */ c from t order by c",
        "Best": "TableReader(Table(t))->Sort",
        "HasWarn": false,
        "Hints": "use_index(@`sel_1` `test`.`t` )"
      },
      {
        "SQL": "select /*+ FORCE_INDEX(t, c_d_e) */ * from t",
        "Best": "IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))",
        "HasWarn": false,
        "Hints": "use_index(@`sel_1` `test`.`t` `c_d_e`)"
      },
      {
        "SQL": "select /*+ FORCE_INDEX(test.t, c_d_e) */ * from t",
        "Best": "IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))",
        "HasWarn": false,
        "Hints": "use_index(@`sel_1` `test`.`t` `c_d_e`)"
      },
      {
        "SQL": "select /*+ USE_INDEX(t, c_d_e) */ * from t t1",
        "Best": "TableReader(Table(t))",
        "HasWarn": true,
        "Hints": "use_index(@`sel_1` `test`.`t1` )"
      },
      {
        "SQL": "select /*+ IGNORE_INDEX(t, c_d_e) */ t1.c from t t1 order by t1.c",
        "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]])",
        "HasWarn": true,
        "Hints": "use_index(@`sel_1` `test`.`t1` `c_d_e`)"
      },
      {
        "SQL": "select /*+ FORCE_INDEX(t, c_d_e) */ * from t t1",
        "Best": "TableReader(Table(t))",
        "HasWarn": true,
        "Hints": "use_index(@`sel_1` `test`.`t1` )"
      },
      {
        "SQL": "select /*+ USE_INDEX(t1, c_d_e) */ * from t t1",
        "Best": "IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))",
        "HasWarn": false,
        "Hints": "use_index(@`sel_1` `test`.`t1` `c_d_e`)"
      },
      {
        "SQL": "select /*+ IGNORE_INDEX(t1, c_d_e) */ t1.c from t t1 order by t1.c",
        "Best": "TableReader(Table(t))->Sort",
        "HasWarn": false,
        "Hints": "use_index(@`sel_1` `test`.`t1` )"
      },
      {
        "SQL": "select /*+ FORCE_INDEX(t1, c_d_e) */ * from t t1",
        "Best": "IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))",
        "HasWarn": false,
        "Hints": "use_index(@`sel_1` `test`.`t1` `c_d_e`)"
      },
      {
        "SQL": "select /*+ USE_INDEX(t1, c_d_e), USE_INDEX(t2, f) */ * from t t1, t t2 where t1.a = t2.b",
        "Best": "LeftHashJoin{IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))->IndexLookUp(Index(t.f)[[NULL,+inf]], Table(t))}(test.t.a,test.t.b)",
        "HasWarn": false,
        "Hints": "use_index(@`sel_1` `test`.`t1` `c_d_e`), use_index(@`sel_1` `test`.`t2` `f`), hash_join(@`sel_1` `test`.`t1`)"
      },
      {
        "SQL": "select /*+ IGNORE_INDEX(t1, c_d_e), IGNORE_INDEX(t2, f), HASH_JOIN(t1) */ * from t t1, t t2 where t1.a = t2.b",
        "Best": "LeftHashJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.b)",
        "HasWarn": false,
        "Hints": "use_index(@`sel_1` `test`.`t1` ), use_index(@`sel_1` `test`.`t2` ), hash_join(@`sel_1` `test`.`t1`)"
      },
      {
        "SQL": "select /*+ FORCE_INDEX(t1, c_d_e), FORCE_INDEX(t2, f) */ * from t t1, t t2 where t1.a = t2.b",
        "Best": "LeftHashJoin{IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))->IndexLookUp(Index(t.f)[[NULL,+inf]], Table(t))}(test.t.a,test.t.b)",
        "HasWarn": false,
        "Hints": "use_index(@`sel_1` `test`.`t1` `c_d_e`), use_index(@`sel_1` `test`.`t2` `f`), hash_join(@`sel_1` `test`.`t1`)"
      },
      {
        "SQL": "select /*+ USE_INDEX(t, c_d_e, f, g) */ * from t order by f",
        "Best": "IndexLookUp(Index(t.f)[[NULL,+inf]], Table(t))",
        "HasWarn": false,
        "Hints": "use_index(@`sel_1` `test`.`t` `f`)"
      },
      {
        "SQL": "select /*+ FORCE_INDEX(t, c_d_e, f, g) */ * from t order by f",
        "Best": "IndexLookUp(Index(t.f)[[NULL,+inf]], Table(t))",
        "HasWarn": false,
        "Hints": "use_index(@`sel_1` `test`.`t` `f`)"
      },
      {
        "SQL": "select /*+ USE_INDEX(t) */ f from t where f > 10",
        "Best": "TableReader(Table(t)->Sel([gt(test.t.f, 10)]))",
        "HasWarn": false,
        "Hints": "use_index(@`sel_1` `test`.`t` )"
      },
      {
        "SQL": "select /*+ FORCE_INDEX(t) */ f from t where f > 10",
        "Best": "TableReader(Table(t)->Sel([gt(test.t.f, 10)]))",
        "HasWarn": false,
        "Hints": "use_index(@`sel_1` `test`.`t` )"
      },
      {
        "SQL": "select /*+ USE_INDEX(t, no_such_index) */ * from t",
        "Best": "TableReader(Table(t))",
        "HasWarn": true,
        "Hints": "use_index(@`sel_1` `test`.`t` )"
      },
      {
        "SQL": "select /*+ IGNORE_INDEX(t, no_such_index) */ * from t",
        "Best": "TableReader(Table(t))",
        "HasWarn": true,
        "Hints": "use_index(@`sel_1` `test`.`t` )"
      },
      {
        "SQL": "select /*+ FORCE_INDEX(t, no_such_index) */ * from t",
        "Best": "TableReader(Table(t))",
        "HasWarn": true,
        "Hints": "use_index(@`sel_1` `test`.`t` )"
      },
      {
        "SQL": "select /*+ USE_INDEX(t, c_d_e), IGNORE_INDEX(t, f) */ c from t order by c",
        "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]])",
        "HasWarn": false,
        "Hints": "use_index(@`sel_1` `test`.`t` `c_d_e`)"
      },
      {
        "SQL": "select /*+ USE_INDEX(t, f), IGNORE_INDEX(t, f) */ c from t order by c",
        "Best": "TableReader(Table(t))->Sort",
        "HasWarn": false,
        "Hints": "use_index(@`sel_1` `test`.`t` )"
      },
      {
        "SQL": "select /*+ USE_INDEX(t, c_d_e), IGNORE_INDEX(t, c_d_e) */ c from t order by c",
        "Best": "TableReader(Table(t))->Sort",
        "HasWarn": false,
        "Hints": "use_index(@`sel_1` `test`.`t` )"
      },
      {
        "SQL": "select /*+ USE_INDEX(t, c_d_e, f), IGNORE_INDEX(t, c_d_e) */ c from t order by c",
        "Best": "IndexLookUp(Index(t.f)[[NULL,+inf]], Table(t))->Sort",
        "HasWarn": false,
        "Hints": "use_index(@`sel_1` `test`.`t` `f`)"
      },
      {
        "SQL": "select /*+ FORCE_INDEX(t, c_d_e), IGNORE_INDEX(t, f) */ c from t order by c",
        "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]])",
        "HasWarn": false,
        "Hints": "use_index(@`sel_1` `test`.`t` `c_d_e`)"
      },
      {
        "SQL": "select /*+ FORCE_INDEX(t, f), IGNORE_INDEX(t, f) */ c from t order by c",
        "Best": "TableReader(Table(t))->Sort",
        "HasWarn": false,
        "Hints": "use_index(@`sel_1` `test`.`t` )"
      },
      {
        "SQL": "select /*+ FORCE_INDEX(t, c_d_e), IGNORE_INDEX(t, c_d_e) */ c from t order by c",
        "Best": "TableReader(Table(t))->Sort",
        "HasWarn": false,
        "Hints": "use_index(@`sel_1` `test`.`t` )"
      },
      {
        "SQL": "select /*+ FORCE_INDEX(t, c_d_e, f), IGNORE_INDEX(t, c_d_e) */ c from t order by c",
        "Best": "IndexLookUp(Index(t.f)[[NULL,+inf]], Table(t))->Sort",
        "HasWarn": false,
        "Hints": "use_index(@`sel_1` `test`.`t` `f`)"
      }
    ]
  },
  {
    "Name": "TestIndexMergeHint",
    "Cases": [
      {
        "SQL": "select /*+ USE_INDEX_MERGE(t, c_d_e, f_g) */ * from t where c < 1 or f > 2",
        "Best": "IndexMergeReader(PartialPlans->[Index(t.c_d_e)[[-inf,1)], Index(t.f_g)[(2,+inf]]], TablePlan->Table(t))",
        "HasWarn": false,
        "Hints": "use_index_merge(@`sel_1` `t` `c_d_e`, `f_g`)"
      },
      {
        "SQL": "select /*+ USE_INDEX_MERGE(t, primary, f_g) */ * from t where a < 1 or f > 2",
        "Best": "IndexMergeReader(PartialPlans->[Table(t), Index(t.f_g)[(2,+inf]]], TablePlan->Table(t))",
        "HasWarn": false,
        "Hints": "use_index_merge(@`sel_1` `t` `primary`, `f_g`)"
      },
      {
        "SQL": "select /*+ USE_INDEX_MERGE(t, primary, f_g, c_d_e) */ * from t where a < 1 or f > 2",
        "Best": "IndexMergeReader(PartialPlans->[Table(t), Index(t.f_g)[(2,+inf]]], TablePlan->Table(t))",
        "HasWarn": false,
        "Hints": "use_index_merge(@`sel_1` `t` `primary`, `f_g`)"
      },
      {
        "SQL": "select /*+ NO_INDEX_MERGE(), USE_INDEX_MERGE(t, primary, f_g, c_d_e) */ * from t where a < 1 or f > 2",
        "Best": "TableReader(Table(t)->Sel([or(lt(test.t.a, 1), gt(test.t.f, 2))]))",
        "HasWarn": true,
        "Hints": "use_index(@`sel_1` `test`.`t` )"
      },
      {
        "SQL": "select /*+ USE_INDEX_MERGE(t1, c_d_e, f_g) */ * from t where c < 1 or f > 2",
        "Best": "TableReader(Table(t)->Sel([or(lt(test.t.c, 1), gt(test.t.f, 2))]))",
        "HasWarn": true,
        "Hints": "use_index(@`sel_1` `test`.`t` )"
      },
      {
        "SQL": "select /*+ NO_INDEX_MERGE(), USE_INDEX_MERGE(t, primary, f_g, c_d_e) */ * from t where a < 1 or f > 2",
        "Best": "TableReader(Table(t)->Sel([or(lt(test.t.a, 1), gt(test.t.f, 2))]))",
        "HasWarn": true,
        "Hints": "use_index(@`sel_1` `test`.`t` )"
      },
      {
        "SQL": "select /*+ USE_INDEX_MERGE(t) USE_INDEX_MERGE(t) */ * from t where c < 1 or f > 2",
        "Best": "IndexMergeReader(PartialPlans->[Index(t.c_d_e)[[-inf,1)], Index(t.f)[(2,+inf]]], TablePlan->Table(t))",
        "HasWarn": false,
        "Hints": "use_index_merge(@`sel_1` `t` `c_d_e`, `f`)"
      },
      {
        "SQL": "select /*+ USE_INDEX_MERGE(db2.t) */ * from t where c < 1 or f > 2",
        "Best": "TableReader(Table(t)->Sel([or(lt(test.t.c, 1), gt(test.t.f, 2))]))",
        "HasWarn": true,
        "Hints": "use_index(@`sel_1` `test`.`t` )"
      },
      {
        "SQL": "select /*+ USE_INDEX_MERGE(db2.t, c_d_e, f_g) */ * from t where c < 1 or f > 2",
        "Best": "TableReader(Table(t)->Sel([or(lt(test.t.c, 1), gt(test.t.f, 2))]))",
        "HasWarn": true,
        "Hints": "use_index(@`sel_1` `test`.`t` )"
      }
    ]
  },
  {
    "Name": "TestDAGPlanBuilderSimpleCase",
    "Cases": [
      {
        "SQL": "select * from t t1 use index(c_d_e)",
        "Best": "IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))"
      },
      {
        "SQL": "select f from t use index() where f = 1",
        "Best": "TableReader(Table(t)->Sel([eq(test.t.f, 1)]))"
      },
      {
        "SQL": "select a from t where a between 1 and 2 order by c",
        "Best": "TableReader(Table(t))->Sort->Projection"
      },
      {
        "SQL": "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)",
        "Best": "TableReader(Table(t)->Sel([or(or(and(gt(test.t.c, 0), lt(test.t.c, 2)), and(gt(test.t.c, 4), lt(test.t.c, 6))), or(and(gt(test.t.c, 8), lt(test.t.c, 10)), or(and(gt(test.t.c, 12), lt(test.t.c, 14)), and(gt(test.t.c, 16), lt(test.t.c, 18)))))]))"
      },
      {
        "SQL": "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)",
        "Best": "Dual"
      },
      {
        "SQL": "select * from t where t.c = 1 and t.e = 1 order by t.b limit 1",
        "Best": "IndexLookUp(Index(t.c_d_e)[[1,1]]->Sel([eq(test.t.e, 1)]), Table(t))->TopN([test.t.b],0,1)"
      },
      {
        "SQL": "select * from t where t.e_str is null",
        "Best": "IndexLookUp(Index(t.e_d_c_str_prefix)[[NULL,NULL]], Table(t))"
      },
      {
        "SQL": "select * from t where t.c is null",
        "Best": "Dual"
      },
      {
        "SQL": "select * from t where t.c = 1 and t.e = 1 order by t.e limit 1",
        "Best": "IndexLookUp(Index(t.c_d_e)[[1,1]]->Sel([eq(test.t.e, 1)]), Table(t))->TopN([test.t.e],0,1)"
      },
      {
        "SQL": "select * from t where t.c = 1 and t.e = 1 order by t.d limit 1",
        "Best": "IndexLookUp(Index(t.c_d_e)[[1,1]]->Sel([eq(test.t.e, 1)])->Limit, Table(t))"
      },
      {
        "SQL": "select c from t where t.c = 1 and t.e = 1 order by t.d limit 1",
        "Best": "IndexReader(Index(t.c_d_e)[[1,1]]->Sel([eq(test.t.e, 1)])->Limit)->Limit->Projection"
      },
      {
        "SQL": "select c from t order by t.a limit 1",
        "Best": "TableReader(Table(t)->Limit)->Limit->Projection"
      },
      {
        "SQL": "select c from t order by t.a + t.b limit 1",
        "Best": "TableReader(Table(t)->TopN([plus(test.t.a, test.t.b)],0,1))->Projection->TopN([Column#14],0,1)->Projection->Projection"
      },
      {
        "SQL": "select c from t  limit 1",
        "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]]->Limit)->Limit"
      },
      {
        "SQL": "select c from t where c = 1 limit 1",
        "Best": "IndexReader(Index(t.c_d_e)[[1,1]]->Limit)->Limit"
      },
      {
        "SQL": "select c from t where c = 1",
        "Best": "IndexReader(Index(t.c_d_e)[[1,1]])"
      },
      {
        "SQL": "select c from t order by c",
        "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]])"
      },
      {
        "SQL": "select c from t where c = 1 order by e",
        "Best": "IndexReader(Index(t.c_d_e)[[1,1]])->Sort->Projection"
      },
      {
        "SQL": "select c, b from t where c = 1 limit 1",
        "Best": "IndexLookUp(Index(t.c_d_e)[[1,1]]->Limit, Table(t))->Projection"
      },
      {
        "SQL": "select c, b from t where c = 1 and e = 1 and b = 1 limit 1",
        "Best": "IndexLookUp(Index(t.c_d_e)[[1,1]]->Sel([eq(test.t.e, 1)]), Table(t)->Sel([eq(test.t.b, 1)])->Limit)->Limit->Projection"
      },
      {
        "SQL": "select c from t where c = 1 order by d, c",
        "Best": "IndexReader(Index(t.c_d_e)[[1,1]])->Sort->Projection"
      },
      {
        "SQL": "select c_str from t where e_str = '1' order by d_str, c_str",
        "Best": "IndexLookUp(Index(t.e_d_c_str_prefix)[[\"1\",\"1\"]], Table(t))->Sort->Projection"
      },
      {
        "SQL": "select c from t where t.c = 1 and t.a > 1 order by t.d limit 1",
        "Best": "IndexReader(Index(t.c_d_e)[[1,1]]->Sel([gt(test.t.a, 1)])->Limit)->Limit->Projection"
      },
      {
        "SQL": "select c from t where t.c = 1 and t.d = 1 order by t.a limit 1",
        "Best": "IndexReader(Index(t.c_d_e)[[1 1,1 1]]->TopN([test.t.a],0,1))->TopN([test.t.a],0,1)->Projection"
      },
      {
        "SQL": "select * from t where t.c = 1 and t.a > 1 order by t.d limit 1",
        "Best": "IndexLookUp(Index(t.c_d_e)[[1,1]]->Sel([gt(test.t.a, 1)])->Limit, Table(t))"
      },
      {
        "SQL": "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'",
        "Best": "IndexLookUp(Index(t.e_d_c_str_prefix)[[\"e\" \"d\" \"abcdefghij\",\"e\" \"d\" \"abcdefghij\"]], Table(t)->Sel([eq(test.t.c_str, abcdefghijk)]))"
      },
      {
        "SQL": "select * from t use index(e_d_c_str_prefix) where t.e_str = b'1110000'",
        "Best": "IndexLookUp(Index(t.e_d_c_str_prefix)[[\"p\",\"p\"]], Table(t))"
      },
      {
        "SQL": "select * from (select * from t use index() order by b) t left join t t1 on t.a=t1.a limit 10",
        "Best": "IndexJoin{TableReader(Table(t)->TopN([test.t.b],0,10))->TopN([test.t.b],0,10)->TableReader(Table(t))}(test.t.a,test.t.a)->Limit"
      },
      {
        "SQL": "select * from ((SELECT 1 a,3 b) UNION (SELECT 2,1) ORDER BY (SELECT 2)) t order by a,b",
        "Best": "UnionAll{Dual->Projection->Dual->Projection}->HashAgg->Sort"
      },
      {
        "SQL": "select * from ((SELECT 1 a,6 b) UNION (SELECT 2,5) UNION (SELECT 2, 4) ORDER BY 1) t order by 1, 2",
        "Best": "UnionAll{Dual->Projection->Projection->Dual->Projection->Projection->Dual->Projection->Projection}->HashAgg->Projection->Sort"
      },
      {
        "SQL": "select * from (select *, NULL as xxx from t) t order by xxx",
        "Best": "TableReader(Table(t))->Projection"
      },
      {
        "SQL": "select * from t use index(f) where f = 1 and a = 1",
        "Best": "PointGet(Index(t.f)[KindInt64 1])->Sel([eq(test.t.a, 1)])"
      },
      {
        "SQL": "select * from t2 use index(b) where b = 1 and a = 1",
        "Best": "PointGet(Index(t2.b)[KindInt64 1])->Sel([eq(test.t2.a, 1)])"
      },
      {
        "SQL": "select f from t where a > 1",
        "Best": "TableReader(Table(t))->Projection"
      },
      {
        "SQL": "select f from t where a > 1 limit 10",
        "Best": "TableReader(Table(t)->Limit)->Limit"
      }
    ]
  },
  {
    "Name": "TestDAGPlanBuilderJoin",
    "Cases": [
      {
        "SQL": "select * from t t1 join t t2 on t1.a = t2.c_str",
        "Best": "LeftHashJoin{TableReader(Table(t))->Projection->TableReader(Table(t))->Projection}(Column#25,Column#26)"
      },
      {
        "SQL": "select * from t t1 join t t2 on t1.b = t2.a",
        "Best": "LeftHashJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.b,test.t.a)"
      },
      {
        "SQL": "select * from t t1 join t t2 on t1.a = t2.a join t t3 on t1.a = t3.a",
        "Best": "MergeInnerJoin{MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->TableReader(Table(t))}(test.t.a,test.t.a)"
      },
      {
        "SQL": "select * from t t1 join t t2 on t1.a = t2.a join t t3 on t1.b = t3.a",
        "Best": "LeftHashJoin{MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->TableReader(Table(t))}(test.t.b,test.t.a)"
      },
      {
        "SQL": "select * from t t1 join t t2 on t1.b = t2.a order by t1.a",
        "Best": "IndexJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.b,test.t.a)"
      },
      {
        "SQL": "select * from t t1 join t t2 on t1.b = t2.a order by t1.a limit 1",
        "Best": "IndexJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.b,test.t.a)->Limit"
      },
      {
        "SQL": "select /*+ TIDB_HJ(t1, t2) */ * from t t1 join t t2 on t1.b = t2.a order by t1.a limit 1",
        "Best": "LeftHashJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.b,test.t.a)->TopN([test.t.a],0,1)"
      },
      {
        "SQL": "select * from t t1 left join t t2 on t1.b = t2.a where 1 = 1 limit 1",
        "Best": "IndexJoin{TableReader(Table(t)->Limit)->Limit->TableReader(Table(t))}(test.t.b,test.t.a)->Limit"
      },
      {
        "SQL": "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",
        "Best": "IndexJoin{PointGet(Index(t.c_d_e)[KindInt64 1 KindInt64 1 KindInt64 1])->TableReader(Table(t))}(test.t.b,test.t.a)->TopN([test.t.a],0,1)"
      },
      {
        "SQL": "select * from t t1 join t t2 on t1.b = t2.b join t t3 on t1.b = t3.b",
        "Best": "LeftHashJoin{LeftHashJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.b,test.t.b)->TableReader(Table(t))}(test.t.b,test.t.b)"
      },
      {
        "SQL": "select * from t t1 join t t2 on t1.a = t2.a order by t1.a",
        "Best": "MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)"
      },
      {
        "SQL": "select * from t t1 left outer join t t2 on t1.a = t2.a right outer join t t3 on t1.a = t3.a",
        "Best": "MergeRightOuterJoin{MergeLeftOuterJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->TableReader(Table(t))}(test.t.a,test.t.a)"
      },
      {
        "SQL": "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",
        "Best": "IndexJoin{IndexJoin{TableReader(Table(t)->Sel([eq(test.t.b, 1)]))->IndexLookUp(Index(t.c_d_e)[[1,1]], Table(t))}(test.t.a,test.t.a)->TableReader(Table(t))}(test.t.a,test.t.a)->Projection"
      },
      {
        "SQL": "select * from t where t.c in (select b from t s where s.a = t.a)",
        "Best": "LeftHashJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)(test.t.c,test.t.b)"
      },
      {
        "SQL": "select t.c in (select b from t s where s.a = t.a) from t",
        "Best": "LeftHashJoin{IndexReader(Index(t.c_d_e)[[NULL,+inf]])->TableReader(Table(t))}(test.t.a,test.t.a)(test.t.c,test.t.b)"
      },
      {
        "SQL": "select /*+ TIDB_SMJ(t1,t2)*/ * from t t1, t t2 where t1.a = t2.b",
        "Best": "MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))->Sort}(test.t.a,test.t.b)"
      },
      {
        "SQL": "select /*+ TIDB_SMJ(t1,t2)*/ * from t t1, t t2 where t1.a = t2.a",
        "Best": "MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)"
      },
      {
        "SQL": "select /*+ TIDB_SMJ(t1,t2)*/ * from t t1, t t2 where t1.a = t2.a order by t2.a",
        "Best": "MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)"
      },
      {
        "SQL": "select /*+ TIDB_SMJ(t1,t2)*/ * from t t1, t t2 where t1.b = t2.b order by t2.a",
        "Best": "MergeInnerJoin{TableReader(Table(t))->Sort->TableReader(Table(t))->Sort}(test.t.b,test.t.b)->Sort"
      },
      {
        "SQL": "select /*+ TIDB_SMJ(t1,t2)*/ * from t t1, t t2 where t1.a = t2.a order by t2.a desc",
        "Best": "MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)"
      },
      {
        "SQL": "select /*+ TIDB_SMJ(t1,t2)*/ * from t t1, t t2 where t1.b = t2.b order by t2.b desc",
        "Best": "MergeInnerJoin{TableReader(Table(t))->Sort->TableReader(Table(t))->Sort}(test.t.b,test.t.b)"
      },
      {
        "SQL": "select /*+ TIDB_SMJ(t1,t2,t3)*/ * from t t1, t t2, t t3 where t1.a = t2.a and t2.a = t3.a",
        "Best": "MergeInnerJoin{MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->TableReader(Table(t))}(test.t.a,test.t.a)"
      },
      {
        "SQL": "select /*+ TIDB_SMJ(t1,t2,t3)*/ * from t t1, t t2, t t3 where t1.a = t2.b and t2.a = t3.b",
        "Best": "MergeInnerJoin{MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))->Sort}(test.t.a,test.t.b)->Sort->TableReader(Table(t))->Sort}(test.t.a,test.t.b)"
      },
      {
        "SQL": "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",
        "Best": "MergeInnerJoin{MergeInnerJoin{IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))->IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))}(test.t.c,test.t.c)(test.t.d,test.t.d)->IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))}(test.t.c,test.t.c)(test.t.d,test.t.d)"
      },
      {
        "SQL": "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",
        "Best": "MergeInnerJoin{MergeInnerJoin{IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))->IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))}(test.t.c,test.t.c)(test.t.d,test.t.d)->IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))}(test.t.c,test.t.c)(test.t.d,test.t.d)"
      },
      {
        "SQL": "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",
        "Best": "MergeLeftOuterJoin{MergeLeftOuterJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->Sort->TableReader(Table(t))}(test.t.a,test.t.a)"
      },
      {
        "SQL": "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",
        "Best": "MergeLeftOuterJoin{MergeLeftOuterJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->TableReader(Table(t))}(test.t.a,test.t.a)"
      },
      {
        "SQL": "select /*+ TIDB_INLJ(t1, t2) */ * from t t1, t t2 where t1.a = t2.a",
        "Best": "IndexJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)"
      },
      {
        "SQL": "select /*+ TIDB_INLJ(t2) */ * from t t1, t t2 where t1.a = t2.c",
        "Best": "IndexJoin{TableReader(Table(t))->IndexLookUp(Index(t.c_d_e)[[NULL,NULL]], Table(t))}(test.t.a,test.t.c)"
      },
      {
        "SQL": "select /*+ TIDB_INLJ(t2) */ t1.a , t2.a from t t1, t t2 where t1.a = t2.c",
        "Best": "IndexJoin{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.c_d_e)[[NULL,NULL]])}(test.t.a,test.t.c)"
      },
      {
        "SQL": "select /*+ TIDB_INLJ(t1, t2) */ t1.a, t2.a from t t1, t t2 where t1.a = t2.a order by t1.c",
        "Best": "IndexJoin{IndexReader(Index(t.c_d_e)[[NULL,+inf]])->TableReader(Table(t))}(test.t.a,test.t.a)->Projection"
      },
      {
        "SQL": "select /*+ TIDB_INLJ(t1, t2) */ t1.a, t2.a from t t1, t t2 where t1.a = t2.a order by t2.c",
        "Best": "IndexJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.a)->Projection"
      },
      {
        "SQL": "select /*+ TIDB_INLJ(t1) */ t1.a , t2.a from t t1, t t2 where t1.a = t2.c",
        "Best": "IndexJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.c,test.t.a)"
      },
      {
        "SQL": "select /*+ TIDB_INLJ(t1, t2) */ * from t t1 left outer join t t2 on t1.a = t2.a and t2.b < 1",
        "Best": "IndexJoin{TableReader(Table(t))->TableReader(Table(t)->Sel([lt(test.t.b, 1)]))}(test.t.a,test.t.a)"
      },
      {
        "SQL": "select /*+ TIDB_INLJ(t1, t2) */ * from t t1 join t t2 on t1.d=t2.d and t2.c = 1",
        "Best": "IndexJoin{TableReader(Table(t))->IndexLookUp(Index(t.c_d_e)[[1 NULL,1 NULL]], Table(t))}(test.t.d,test.t.d)"
      },
      {
        "SQL": "select /*+ TIDB_INLJ(t1, t2) */ * from t t1 left outer join t t2 on t1.a = t2.b",
        "Best": "LeftHashJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.b)"
      },
      {
        "SQL": "select /*+ TIDB_INLJ(t2) */ * from t t1 right outer join t t2 on t1.a = t2.b",
        "Best": "RightHashJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.b)"
      },
      {
        "SQL": "select /*+ TIDB_INLJ(t2) */ * from t t1 where t1.a in (select a from t t2)",
        "Best": "MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)"
      },
      {
        "SQL": "select /*+ TIDB_INLJ(t1) */ * from t t1 where t1.a in (select a from t t2)",
        "Best": "IndexJoin{TableReader(Table(t))->IndexReader(Index(t.f)[[NULL,+inf]])}(test.t.a,test.t.a)"
      },
      {
        "SQL": "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t1.c=t2.c and t1.f=t2.f",
        "Best": "IndexJoin{TableReader(Table(t))->IndexLookUp(Index(t.c_d_e)[[NULL,NULL]], Table(t))}(test.t.c,test.t.c)"
      },
      {
        "SQL": "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t1.a = t2.a and t1.f=t2.f",
        "Best": "IndexJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)"
      },
      {
        "SQL": "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t1.f=t2.f and t1.a=t2.a",
        "Best": "IndexJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)"
      },
      {
        "SQL": "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t1.a=t2.a and t2.a in (1, 2)",
        "Best": "IndexJoin{BatchPointGet(Handle(t.a)[1 2])->TableReader(Table(t)->Sel([in(test.t.a, 1, 2)]))}(test.t.a,test.t.a)"
      },
      {
        "SQL": "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",
        "Best": "IndexJoin{TableReader(Table(t)->Sel([eq(test.t.b, 1)]))->IndexLookUp(Index(t.c_d_e)[[1 NULL,1 NULL]], Table(t))}"
      },
      {
        "SQL": "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",
        "Best": "LeftHashJoin{IndexLookUp(Index(t.c_d_e)[[1,1]], Table(t))->IndexLookUp(Index(t.c_d_e)[[1,1]], Table(t))}(test.t.b,test.t.b)"
      },
      {
        "SQL": "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t2.c > t1.d-10 and t2.c < t1.d+10",
        "Best": "LeftHashJoin{TableReader(Table(t))->TableReader(Table(t))}"
      },
      {
        "SQL": "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",
        "Best": "LeftHashJoin{TableReader(Table(t)->Sel([eq(test.t.b, 1)]))->PointGet(Index(t.c_d_e)[KindInt64 1 KindInt64 2 KindInt64 4])}"
      },
      {
        "SQL": "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",
        "Best": "LeftHashJoin{TableReader(Table(t))->IndexLookUp(Index(t.c_d_e)[(1 1 10,1 1 20)], Table(t))}"
      }
    ]
  },
  {
    "Name": "TestDAGPlanBuilderSubquery",
    "Cases": [
      {
        "SQL": "select * from t where exists (select s.a from t s having sum(s.a) = t.a )",
        "Best": "LeftHashJoin{TableReader(Table(t))->Projection->IndexReader(Index(t.f)[[NULL,+inf]]->StreamAgg)->StreamAgg}(Column#27,Column#25)"
      },
      {
        "SQL": "select * from t where exists (select s.a from t s having sum(s.a) = t.a ) order by t.a",
        "Best": "LeftHashJoin{TableReader(Table(t))->Projection->IndexReader(Index(t.f)[[NULL,+inf]]->StreamAgg)->StreamAgg}(Column#27,Column#25)->Sort"
      },
      {
        "SQL": "select * from t where a in (select s.a from t s) order by t.a",
        "Best": "MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)"
      },
      {
        "SQL": "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 )",
        "Best": "LeftHashJoin{TableReader(Table(t))->Projection->MergeSemiJoin{IndexReader(Index(t.c_d_e)[[NULL,+inf]])->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.c,test.t.c)(test.t.d,test.t.d)->Projection->StreamAgg}(Column#39,Column#37)"
      },
      {
        "SQL": "select * from t where a in (select a from t) order by b",
        "Best": "MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->Sort"
      },
      {
        "SQL": "select t.c in (select count(*) from t s, t t1 where s.a = t.a and s.a = t1.a) from t",
        "Best": "Apply{IndexReader(Index(t.c_d_e)[[NULL,+inf]])->MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->StreamAgg}->Projection"
      },
      {
        "SQL": "select (select count(*) from t s, t t1 where s.a = t.a and s.a = t1.a) from t",
        "Best": "MergeLeftOuterJoin{TableReader(Table(t))->MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->Projection}(test.t.a,test.t.a)->Projection"
      },
      {
        "SQL": "select (select count(*) from t s, t t1 where s.a = t.a and s.a = t1.a) from t order by t.a",
        "Best": "MergeLeftOuterJoin{TableReader(Table(t))->MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->Projection}(test.t.a,test.t.a)->Projection->Projection"
      }
    ]
  },
  {
    "Name": "TestDAGPlanTopN",
    "Cases": [
      {
        "SQL": "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",
        "Best": "LeftHashJoin{LeftHashJoin{TableReader(Table(t)->Limit)->Limit->TableReader(Table(t))}(test.t.b,test.t.b)->TopN([test.t.a],0,1)->TableReader(Table(t))}(test.t.b,test.t.b)->TopN([test.t.a],0,1)"
      },
      {
        "SQL": "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",
        "Best": "LeftHashJoin{LeftHashJoin{TableReader(Table(t)->TopN([test.t.b],0,1))->TopN([test.t.b],0,1)->TableReader(Table(t))}(test.t.b,test.t.b)->TopN([test.t.b],0,1)->TableReader(Table(t))}(test.t.b,test.t.b)->TopN([test.t.b],0,1)"
      },
      {
        "SQL": "select * from t t1 left join t t2 on t1.b = t2.b left join t t3 on t2.b = t3.b limit 1",
        "Best": "LeftHashJoin{LeftHashJoin{TableReader(Table(t)->Limit)->Limit->TableReader(Table(t))}(test.t.b,test.t.b)->Limit->TableReader(Table(t))}(test.t.b,test.t.b)->Limit"
      },
      {
        "SQL": "select * from t where b = 1 and c = 1 order by c limit 1",
        "Best": "IndexLookUp(Index(t.c_d_e)[[1,1]], Table(t)->Sel([eq(test.t.b, 1)]))->Limit"
      },
      {
        "SQL": "select * from t where c = 1 order by c limit 1",
        "Best": "IndexLookUp(Index(t.c_d_e)[[1,1]]->Limit, Table(t))"
      },
      {
        "SQL": "select * from t order by a limit 1",
        "Best": "TableReader(Table(t)->Limit)->Limit"
      },
      {
        "SQL": "select c from t order by c limit 1",
        "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]]->Limit)->Limit"
      }
    ]
  },
  {
    "Name": "TestDAGPlanBuilderBasePhysicalPlan",
    "Cases": [
      {
        "SQL": "select * from t order by b limit 1 for update",
        "Best": "TableReader(Table(t)->TopN([test.t.b],0,1))->TopN([test.t.b],0,1)->Lock",
        "Hints": "use_index(@`sel_1` `test`.`t` )"
      },
      {
        "SQL": "update t set a = 5 where b < 1 order by d limit 1",
        "Best": "TableReader(Table(t)->Sel([lt(test.t.b, 1)])->TopN([test.t.d],0,1))->TopN([test.t.d],0,1)->Update",
        "Hints": "use_index(@`upd_1` `test`.`t` )"
      },
      {
        "SQL": "update t set a = 5",
        "Best": "TableReader(Table(t))->Update",
        "Hints": "use_index(@`upd_1` `test`.`t` )"
      },
      {
        "SQL": "delete /*+ TIDB_INLJ(t1, t2) */ t1 from t t1, t t2 where t1.c=t2.c",
        "Best": "IndexJoin{TableReader(Table(t))->IndexLookUp(Index(t.c_d_e)[[NULL,NULL]], Table(t))}(test.t.c,test.t.c)->Delete",
        "Hints": "use_index(@`del_1` `test`.`t1` ), use_index(@`del_1` `test`.`t2` `c_d_e`), inl_join(@`del_1` `test`.`t2`)"
      },
      {
        "SQL": "delete /*+ TIDB_SMJ(t1, t2) */ from t1 using t t1, t t2 where t1.c=t2.c",
        "Best": "MergeInnerJoin{IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))->IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))}(test.t.c,test.t.c)->Delete",
        "Hints": "use_index(@`del_1` `test`.`t1` `c_d_e`), use_index(@`del_1` `test`.`t2` `c_d_e`), merge_join(@`del_1` `test`.`t1`)"
      },
      {
        "SQL": "update /*+ TIDB_SMJ(t1, t2) */ t t1, t t2 set t1.c=1, t2.c=1 where t1.a=t2.a",
        "Best": "MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->Update",
        "Hints": "use_index(@`upd_1` `test`.`t1` ), use_index(@`upd_1` `test`.`t2` ), merge_join(@`upd_1` `test`.`t1`)"
      },
      {
        "SQL": "update /*+ TIDB_HJ(t1, t2) */ t t1, t t2 set t1.c=1, t2.c=1 where t1.a=t2.a",
        "Best": "LeftHashJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->Update",
        "Hints": "use_index(@`upd_1` `test`.`t1` ), use_index(@`upd_1` `test`.`t2` ), hash_join(@`upd_1` `test`.`t1`)"
      },
      {
        "SQL": "delete from t where b < 1 order by d limit 1",
        "Best": "TableReader(Table(t)->Sel([lt(test.t.b, 1)])->TopN([test.t.d],0,1))->TopN([test.t.d],0,1)->Delete",
        "Hints": "use_index(@`del_1` `test`.`t` )"
      },
      {
        "SQL": "delete from t",
        "Best": "TableReader(Table(t))->Delete",
        "Hints": "use_index(@`del_1` `test`.`t` )"
      },
      {
        "SQL": "delete from t use index(c_d_e) where b = 1",
        "Best": "IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t)->Sel([eq(test.t.b, 1)]))->Delete",
        "Hints": "use_index(@`del_1` `test`.`t` `c_d_e`)"
      },
      {
        "SQL": "insert into t select * from t where b < 1 order by d limit 1",
        "Best": "TableReader(Table(t)->Sel([lt(test.t.b, 1)])->TopN([test.t.d],0,1))->TopN([test.t.d],0,1)->Insert",
        "Hints": "use_index(@`sel_1` `test`.`t` )"
      },
      {
        "SQL": "insert into t (a, b, c, e, f, g) values(0,0,0,0,0,0)",
        "Best": "Insert",
        "Hints": ""
      },
      {
        "SQL": "select 1",
        "Best": "Dual->Projection",
        "Hints": ""
      },
      {
        "SQL": "select * from t where false",
        "Best": "Dual",
        "Hints": ""
      },
      {
        "SQL": "show tables",
        "Best": "Show",
        "Hints": ""
      }
    ]
  },
  {
    "Name": "TestDAGPlanBuilderUnion",
    "Cases": [
      {
        "SQL": "select * from t union all select * from t",
        "Best": "UnionAll{TableReader(Table(t))->TableReader(Table(t))}"
      },
      {
        "SQL": "select * from t union all (select * from t) order by a ",
        "Best": "UnionAll{TableReader(Table(t))->TableReader(Table(t))}->Sort"
      },
      {
        "SQL": "select * from t union all (select * from t) limit 1",
        "Best": "UnionAll{TableReader(Table(t)->Limit)->Limit->TableReader(Table(t)->Limit)->Limit}->Limit"
      },
      {
        "SQL": "select a from t union all (select c from t) order by a limit 1",
        "Best": "UnionAll{TableReader(Table(t)->Limit)->Limit->IndexReader(Index(t.c_d_e)[[NULL,+inf]]->Limit)->Limit}->TopN([Column#25],0,1)"
      }
    ]
  },
  {
    "Name": "TestDAGPlanBuilderUnionScan",
    "Cases": [
      {
        "SQL": "select * from t",
        "Best": "TableReader(Table(t))->UnionScan([])->Projection"
      },
      {
        "SQL": "select * from t where b = 1",
        "Best": "TableReader(Table(t)->Sel([eq(test.t.b, 1)]))->UnionScan([eq(test.t.b, 1)])->Projection"
      },
      {
        "SQL": "select * from t where a = 1",
        "Best": "TableReader(Table(t)->Sel([eq(test.t.a, 1)]))->UnionScan([eq(test.t.a, 1)])->Projection"
      },
      {
        "SQL": "select * from t where a = 1 order by a",
        "Best": "TableReader(Table(t)->Sel([eq(test.t.a, 1)]))->UnionScan([eq(test.t.a, 1)])->Projection->Sort"
      },
      {
        "SQL": "select * from t where a = 1 order by b",
        "Best": "TableReader(Table(t)->Sel([eq(test.t.a, 1)]))->UnionScan([eq(test.t.a, 1)])->Projection->Sort"
      },
      {
        "SQL": "select * from t where a = 1 limit 1",
        "Best": "TableReader(Table(t)->Sel([eq(test.t.a, 1)]))->UnionScan([eq(test.t.a, 1)])->Limit"
      },
      {
        "SQL": "select * from t where c = 1",
        "Best": "TableReader(Table(t)->Sel([eq(test.t.c, 1)]))->UnionScan([eq(test.t.c, 1)])->Projection"
      },
      {
        "SQL": "select c from t where c = 1",
        "Best": "TableReader(Table(t)->Sel([eq(test.t.c, 1)]))->UnionScan([eq(test.t.c, 1)])->Projection"
      }
    ]
  },
  {
    "Name": "TestDAGPlanBuilderAgg",
    "Cases": [
      {
        "SQL": "select distinct b from t",
        "Best": "TableReader(Table(t)->HashAgg)->HashAgg"
      },
      {
        "SQL": "select count(*) from (select * from t order by b) t group by b",
        "Best": "TableReader(Table(t))->Sort->StreamAgg"
      },
      {
        "SQL": "select count(*), x from (select b as bbb, a + 1 as x from (select * from t order by b) t) t group by bbb",
        "Best": "TableReader(Table(t))->Sort->Projection->StreamAgg"
      },
      {
        "SQL": "select sum(a), avg(b + c) from t group by d",
        "Best": "TableReader(Table(t)->HashAgg)->HashAgg"
      },
      {
        "SQL": "select sum(distinct a), avg(b + c) from t group by d",
        "Best": "TableReader(Table(t)->HashAgg)->HashAgg"
      },
      {
        "SQL": "select sum(e), avg(e + c) from t where c = 1 group by (c + d)",
        "Best": "IndexReader(Index(t.c_d_e)[[1,1]]->HashAgg)->HashAgg"
      },
      {
        "SQL": "select sum(e), avg(e + c) from t where c = 1 group by c",
        "Best": "IndexReader(Index(t.c_d_e)[[1,1]])->Projection->StreamAgg"
      },
      {
        "SQL": "select sum(e), avg(e + c) from t where c = 1 group by e",
        "Best": "IndexReader(Index(t.c_d_e)[[1,1]])->Projection->HashAgg"
      },
      {
        "SQL": "select sum(e), avg(b + c) from t where c = 1 and e = 1 group by d",
        "Best": "IndexLookUp(Index(t.c_d_e)[[1,1]]->Sel([eq(test.t.e, 1)]), Table(t))->Projection->Projection->StreamAgg"
      },
      {
        "SQL": "select sum(e), avg(b + c) from t where c = 1 and b = 1",
        "Best": "IndexLookUp(Index(t.c_d_e)[[1,1]], Table(t)->Sel([eq(test.t.b, 1)]))->Projection->StreamAgg"
      },
      {
        "SQL": "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",
        "Best": "IndexLookUp(Index(t.c_d_e)[[1,1]]->Sel([eq(test.t.e, 1)]), Table(t)->Sel([eq(test.t.b, 1)]))->Projection->Projection->StreamAgg->Sort"
      },
      {
        "SQL": "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",
        "Best": "IndexLookUp(Index(t.c_d_e)[[1,1]]->Sel([eq(test.t.e, 1)]), Table(t)->Sel([eq(test.t.b, 1)]))->Projection->Projection->StreamAgg->Sort"
      },
      {
        "SQL": "select sum(to_base64(e)) from t where c = 1",
        "Best": "IndexReader(Index(t.c_d_e)[[1,1]])->Projection->StreamAgg"
      },
      {
        "SQL": "select (select count(1) k from t s where s.a = t.a having k != 0) from t",
        "Best": "MergeLeftOuterJoin{TableReader(Table(t))->TableReader(Table(t))->Projection}(test.t.a,test.t.a)->Projection"
      },
      {
        "SQL": "select sum(to_base64(e)) from t group by e,d,c order by c",
        "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]])->Projection->StreamAgg->Projection"
      },
      {
        "SQL": "select sum(e+1) from t group by e,d,c order by c",
        "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]]->StreamAgg)->StreamAgg->Projection"
      },
      {
        "SQL": "select sum(to_base64(e)) from t group by e,d,c order by c,e",
        "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]])->Projection->StreamAgg->Sort->Projection"
      },
      {
        "SQL": "select sum(e+1) from t group by e,d,c order by c,e",
        "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]]->StreamAgg)->StreamAgg->Sort->Projection"
      },
      {
        "SQL": "select count(*) from t group by g order by g limit 10",
        "Best": "IndexReader(Index(t.g)[[NULL,+inf]]->StreamAgg)->StreamAgg->Limit->Projection"
      },
      {
        "SQL": "select count(*) from t group by g limit 10",
        "Best": "IndexReader(Index(t.g)[[NULL,+inf]]->StreamAgg)->StreamAgg->Limit"
      },
      {
        "SQL": "select count(*) from t group by g order by g",
        "Best": "IndexReader(Index(t.g)[[NULL,+inf]]->StreamAgg)->StreamAgg->Projection"
      },
      {
        "SQL": "select count(*) from t group by g order by g desc limit 1",
        "Best": "IndexReader(Index(t.g)[[NULL,+inf]]->StreamAgg)->StreamAgg->Limit->Projection"
      },
      {
        "SQL": "select count(*) from t group by b order by b limit 10",
        "Best": "TableReader(Table(t)->HashAgg)->HashAgg->TopN([test.t.b],0,10)->Projection"
      },
      {
        "SQL": "select count(*) from t group by b order by b",
        "Best": "TableReader(Table(t)->HashAgg)->HashAgg->Sort->Projection"
      },
      {
        "SQL": "select count(*) from t group by b limit 10",
        "Best": "TableReader(Table(t)->HashAgg)->HashAgg->Limit"
      },
      {
        "SQL": "select sum(a.g), sum(b.g) from t a join t b on a.g = b.g group by a.g",
        "Best": "MergeInnerJoin{IndexReader(Index(t.g)[[NULL,+inf]])->IndexReader(Index(t.g)[[NULL,+inf]])}(test.t.g,test.t.g)->Projection->StreamAgg"
      },
      {
        "SQL": "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",
        "Best": "IndexJoin{IndexReader(Index(t.g)[(60,+inf]])->IndexReader(Index(t.g)[[NULL,NULL]]->Sel([gt(test.t.g, 60)]))}(test.t.g,test.t.g)->Projection->StreamAgg->Limit->Projection"
      },
      {
        "SQL": "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",
        "Best": "MergeInnerJoin{IndexReader(Index(t.g)[[NULL,+inf]]->Sel([gt(test.t.a, 5)]))->IndexReader(Index(t.g)[[NULL,+inf]])}(test.t.g,test.t.g)->Projection->StreamAgg->Limit->Projection"
      },
      {
        "SQL": "select sum(d) from t",
        "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]]->StreamAgg)->StreamAgg"
      }
    ]
  },
  {
    "Name": "TestRefine",
    "Cases": [
      {
        "SQL": "select a from t where c is not null",
        "Best": "IndexReader(Index(t.f)[[NULL,+inf]])"
      },
      {
        "SQL": "select a from t where c >= 4",
        "Best": "IndexReader(Index(t.c_d_e)[[4,+inf]])->Projection"
      },
      {
        "SQL": "select a from t where c <= 4",
        "Best": "IndexReader(Index(t.c_d_e)[[-inf,4]])->Projection"
      },
      {
        "SQL": "select a from t where c = 4 and d = 5 and e = 6",
        "Best": "PointGet(Index(t.c_d_e)[KindInt64 4 KindInt64 5 KindInt64 6])->Projection"
      },
      {
        "SQL": "select a from t where d = 4 and c = 5",
        "Best": "IndexReader(Index(t.c_d_e)[[5 4,5 4]])->Projection"
      },
      {
        "SQL": "select a from t where c = 4 and e < 5",
        "Best": "IndexReader(Index(t.c_d_e)[[4,4]]->Sel([lt(test.t.e, 5)]))->Projection"
      },
      {
        "SQL": "select a from t where c = 4 and d <= 5 and d > 3",
        "Best": "IndexReader(Index(t.c_d_e)[(4 3,4 5]])->Projection"
      },
      {
        "SQL": "select a from t where d <= 5 and d > 3",
        "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]]->Sel([le(test.t.d, 5) gt(test.t.d, 3)]))->Projection"
      },
      {
        "SQL": "select a from t where c between 1 and 2",
        "Best": "IndexReader(Index(t.c_d_e)[[1,2]])->Projection"
      },
      {
        "SQL": "select a from t where c not between 1 and 2",
        "Best": "IndexReader(Index(t.c_d_e)[[-inf,1) (2,+inf]])->Projection"
      },
      {
        "SQL": "select a from t where c <= 5 and c >= 3 and d = 1",
        "Best": "IndexReader(Index(t.c_d_e)[[3,5]]->Sel([eq(test.t.d, 1)]))->Projection"
      },
      {
        "SQL": "select a from t where c = 1 or c = 2 or c = 3",
        "Best": "IndexReader(Index(t.c_d_e)[[1,3]])->Projection"
      },
      {
        "SQL": "select b from t where c = 1 or c = 2 or c = 3 or c = 4 or c = 5",
        "Best": "TableReader(Table(t)->Sel([or(or(eq(test.t.c, 1), eq(test.t.c, 2)), or(eq(test.t.c, 3), or(eq(test.t.c, 4), eq(test.t.c, 5))))]))->Projection"
      },
      {
        "SQL": "select a from t where c = 5",
        "Best": "IndexReader(Index(t.c_d_e)[[5,5]])->Projection"
      },
      {
        "SQL": "select a from t where c = 5 and b = 1",
        "Best": "IndexLookUp(Index(t.c_d_e)[[5,5]], Table(t)->Sel([eq(test.t.b, 1)]))->Projection"
      },
      {
        "SQL": "select a from t where not a",
        "Best": "PointGet(Handle(t.a)0)"
      },
      {
        "SQL": "select a from t where c in (1)",
        "Best": "IndexReader(Index(t.c_d_e)[[1,1]])->Projection"
      },
      {
        "SQL": "select a from t where c in ('1')",
        "Best": "IndexReader(Index(t.c_d_e)[[1,1]])->Projection"
      },
      {
        "SQL": "select a from t where c = 1.0",
        "Best": "IndexReader(Index(t.c_d_e)[[1,1]])->Projection"
      },
      {
        "SQL": "select a from t where c in (1) and d > 3",
        "Best": "IndexReader(Index(t.c_d_e)[(1 3,1 +inf]])->Projection"
      },
      {
        "SQL": "select a from t where c in (1, 2, 3) and (d > 3 and d < 4 or d > 5 and d < 6)",
        "Best": "Dual->Projection"
      },
      {
        "SQL": "select a from t where c in (1, 2, 3) and (d > 2 and d < 4 or d > 5 and d < 7)",
        "Best": "IndexReader(Index(t.c_d_e)[[1 3,1 3] [1 6,1 6] [2 3,2 3] [2 6,2 6] [3 3,3 3] [3 6,3 6]])->Projection"
      },
      {
        "SQL": "select a from t where c in (1, 2, 3)",
        "Best": "IndexReader(Index(t.c_d_e)[[1,1] [2,2] [3,3]])->Projection"
      },
      {
        "SQL": "select a from t where c in (1, 2, 3) and d in (1,2) and e = 1",
        "Best": "BatchPointGet(Index(t.c_d_e)[[KindInt64 1 KindInt64 1 KindInt64 1] [KindInt64 1 KindInt64 2 KindInt64 1] [KindInt64 2 KindInt64 1 KindInt64 1] [KindInt64 2 KindInt64 2 KindInt64 1] [KindInt64 3 KindInt64 1 KindInt64 1] [KindInt64 3 KindInt64 2 KindInt64 1]])->Projection"
      },
      {
        "SQL": "select a from t where d in (1, 2, 3)",
        "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]]->Sel([in(test.t.d, 1, 2, 3)]))->Projection"
      },
      {
        "SQL": "select a from t where c not in (1)",
        "Best": "IndexReader(Index(t.c_d_e)[[-inf,1) (1,+inf]])->Projection"
      },
      {
        "SQL": "select a from t use index(c_d_e) where c != 1",
        "Best": "IndexReader(Index(t.c_d_e)[[-inf,1) (1,+inf]])->Projection"
      },
      {
        "SQL": "select a from t where c_str like ''",
        "Best": "IndexReader(Index(t.c_d_e_str)[[\"\",\"\"]])->Projection"
      },
      {
        "SQL": "select a from t where c_str like 'abc'",
        "Best": "IndexReader(Index(t.c_d_e_str)[[\"abc\",\"abc\"]])->Projection"
      },
      {
        "SQL": "select a from t where c_str not like 'abc'",
        "Best": "IndexReader(Index(t.c_d_e_str)[[NULL,+inf]]->Sel([not(like(test.t.c_str, abc, 92))]))->Projection"
      },
      {
        "SQL": "select a from t where not (c_str like 'abc' or c_str like 'abd')",
        "Best": "IndexReader(Index(t.c_d_e_str)[[NULL,+inf]]->Sel([and(not(like(test.t.c_str, abc, 92)), not(like(test.t.c_str, abd, 92)))]))->Projection"
      },
      {
        "SQL": "select a from t where c_str like '_abc'",
        "Best": "IndexReader(Index(t.c_d_e_str)[[NULL,+inf]]->Sel([like(test.t.c_str, _abc, 92)]))->Projection"
      },
      {
        "SQL": "select a from t where c_str like 'abc%'",
        "Best": "IndexReader(Index(t.c_d_e_str)[[\"abc\",\"abd\")])->Projection"
      },
      {
        "SQL": "select a from t where c_str like 'abc_'",
        "Best": "IndexReader(Index(t.c_d_e_str)[(\"abc\",\"abd\")]->Sel([like(test.t.c_str, abc_, 92)]))->Projection"
      },
      {
        "SQL": "select a from t where c_str like 'abc%af'",
        "Best": "IndexReader(Index(t.c_d_e_str)[[\"abc\",\"abd\")]->Sel([like(test.t.c_str, abc%af, 92)]))->Projection"
      },
      {
        "SQL": "select a from t where c_str like 'abc\\_' escape ''",
        "Best": "IndexReader(Index(t.c_d_e_str)[[\"abc_\",\"abc_\"]])->Projection"
      },
      {
        "SQL": "select a from t where c_str like 'abc\\_'",
        "Best": "IndexReader(Index(t.c_d_e_str)[[\"abc_\",\"abc_\"]])->Projection"
      },
      {
        "SQL": "select a from t where c_str like 'abc\\\\_'",
        "Best": "IndexReader(Index(t.c_d_e_str)[[\"abc_\",\"abc_\"]])->Projection"
      },
      {
        "SQL": "select a from t where c_str like 'abc\\_%'",
        "Best": "IndexReader(Index(t.c_d_e_str)[[\"abc_\",\"abc`\")])->Projection"
      },
      {
        "SQL": "select a from t where c_str like 'abc=_%' escape '='",
        "Best": "IndexReader(Index(t.c_d_e_str)[[\"abc_\",\"abc`\")])->Projection"
      },
      {
        "SQL": "select a from t where c_str like 'abc\\__'",
        "Best": "IndexReader(Index(t.c_d_e_str)[(\"abc_\",\"abc`\")]->Sel([like(test.t.c_str, abc\\__, 92)]))->Projection"
      },
      {
        "SQL": "select a from t where c_str like 123",
        "Best": "IndexReader(Index(t.c_d_e_str)[[\"123\",\"123\"]])->Projection"
      },
      {
        "SQL": "select a from t where c = 1.9 and d > 3",
        "Best": "Dual"
      },
      {
        "SQL": "select a from t where c < 1.1",
        "Best": "IndexReader(Index(t.c_d_e)[[-inf,2)])->Projection"
      },
      {
        "SQL": "select a from t where c <= 1.9",
        "Best": "IndexReader(Index(t.c_d_e)[[-inf,1]])->Projection"
      },
      {
        "SQL": "select a from t where c >= 1.1",
        "Best": "IndexReader(Index(t.c_d_e)[[2,+inf]])->Projection"
      },
      {
        "SQL": "select a from t where c > 1.9",
        "Best": "IndexReader(Index(t.c_d_e)[(1,+inf]])->Projection"
      },
      {
        "SQL": "select a from t where c = 123456789098765432101234",
        "Best": "Dual"
      },
      {
        "SQL": "select a from t where c = 'hanfei'",
        "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]]->Sel([eq(cast(test.t.c, double BINARY), cast(hanfei, double BINARY))]))->Projection"
      }
    ]
  },
  {
    "Name": "TestAggEliminator",
    "Cases": [
      {
        "SQL": "select max(a) from t;",
        "Best": "TableReader(Table(t)->Limit)->Limit->StreamAgg"
      },
      {
        "SQL": "select min(a) from t;",
        "Best": "TableReader(Table(t)->Limit)->Limit->StreamAgg"
      },
      {
        "SQL": "select min(c_str) from t;",
        "Best": "IndexReader(Index(t.c_d_e_str)[[-inf,+inf]]->Limit)->Limit->StreamAgg"
      },
      {
        "SQL": "select max(a), b from t;",
        "Best": "TableReader(Table(t)->HashAgg)->HashAgg"
      },
      {
        "SQL": "select max(a+1) from t;",
        "Best": "IndexReader(Index(t.f)[[NULL,+inf]]->TopN([plus(test.t.a, 1) true],0,1))->Projection->TopN([Column#40 true],0,1)->Projection->Projection->StreamAgg"
      },
      {
        "SQL": "select max(a), min(a) from t;",
        "Best": "RightHashJoin{TableReader(Table(t)->Limit)->Limit->StreamAgg->TableReader(Table(t)->Limit)->Limit->StreamAgg}"
      },
      {
        "SQL": "select max(a), min(a) from t where a > 10",
        "Best": "RightHashJoin{TableReader(Table(t)->Limit)->Limit->StreamAgg->TableReader(Table(t)->Limit)->Limit->StreamAgg}"
      },
      {
        "SQL": "select max(d), min(d) from t where c = 1 and d > 10",
        "Best": "LeftHashJoin{IndexReader(Index(t.c_d_e)[(1 10,1 +inf]]->Limit)->Limit->StreamAgg->IndexReader(Index(t.c_d_e)[(1 10,1 +inf]]->Limit)->Limit->StreamAgg}"
      },
      {
        "SQL": "select max(a), max(c), min(f) from t",
        "Best": "LeftHashJoin{RightHashJoin{TableReader(Table(t)->Limit)->Limit->StreamAgg->IndexReader(Index(t.c_d_e)[[NULL,+inf]]->Limit)->Limit->StreamAgg}->IndexReader(Index(t.f)[[NULL,+inf]]->Limit)->Limit->StreamAgg}"
      },
      {
        "SQL": "select max(a), max(b) from t",
        "Best": "TableReader(Table(t)->HashAgg)->HashAgg"
      },
      {
        "SQL": "select max(a), max(c) from t where c > 10",
        "Best": "IndexReader(Index(t.c_d_e)[(10,+inf]]->HashAgg)->HashAgg"
      },
      {
        "SQL": "select max(a), min(a) from t where a * 3 + 10 < 100",
        "Best": "IndexReader(Index(t.f)[[NULL,+inf]]->Sel([lt(plus(mul(test.t.a, 3), 10), 100)])->HashAgg)->HashAgg"
      },
      {
        "SQL": "select max(a) from t group by b;",
        "Best": "TableReader(Table(t)->HashAgg)->HashAgg"
      },
      {
        "SQL": "select max(a) from (select t1.a from t t1 join t t2 on t1.a=t2.a) t",
        "Best": "MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->Limit->StreamAgg"
      }
    ]
  },
  {
    "Name": "TestUnmatchedTableInHint",
    "Cases": [
      {
        "SQL": "SELECT /*+ TIDB_SMJ(t3, t4) */ * from t t1, t t2 where t1.a = t2.a",
        "Warning": "[planner:1815]There are no matching table names for (t3, t4) in optimizer hint /*+ MERGE_JOIN(t3, t4) */ or /*+ TIDB_SMJ(t3, t4) */. Maybe you can use the table alias name"
      },
      {
        "SQL": "SELECT /*+ TIDB_HJ(t3, t4) */ * from t t1, t t2 where t1.a = t2.a",
        "Warning": "[planner:1815]There are no matching table names for (t3, t4) in optimizer hint /*+ HASH_JOIN(t3, t4) */ or /*+ TIDB_HJ(t3, t4) */. Maybe you can use the table alias name"
      },
      {
        "SQL": "SELECT /*+ TIDB_INLJ(t3, t4) */ * from t t1, t t2 where t1.a = t2.a",
        "Warning": "[planner:1815]There are no matching table names for (t3, t4) in optimizer hint /*+ INL_JOIN(t3, t4) */ or /*+ TIDB_INLJ(t3, t4) */. Maybe you can use the table alias name"
      },
      {
        "SQL": "SELECT /*+ TIDB_SMJ(t1, t2) */ * from t t1, t t2 where t1.a = t2.a",
        "Warning": ""
      },
      {
        "SQL": "SELECT /*+ TIDB_SMJ(t3, t4) */ * from t t1, t t2, t t3 where t1.a = t2.a and t2.a = t3.a",
        "Warning": "[planner:1815]There are no matching table names for (t4) in optimizer hint /*+ MERGE_JOIN(t3, t4) */ or /*+ TIDB_SMJ(t3, t4) */. Maybe you can use the table alias name"
      }
    ]
  },
  {
    "Name": "TestJoinHints",
    "Cases": [
      {
        "SQL": "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;",
        "Best": "MergeInnerJoin{TableReader(Table(t))->IndexJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)}(test.t.a,test.t.a)->Projection",
        "Warning": "",
        "Hints": "use_index(@`sel_1` `test`.`t3` ), use_index(@`sel_1` `test`.`t1` ), use_index(@`sel_1` `test`.`t2` ), inl_join(@`sel_1` `test`.`t1`), merge_join(@`sel_1` `test`.`t3`)"
      },
      {
        "SQL": "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;",
        "Best": "MergeInnerJoin{TableReader(Table(t))->IndexJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)}(test.t.a,test.t.a)->Projection",
        "Warning": "",
        "Hints": "use_index(@`sel_1` `test`.`t3` ), use_index(@`sel_1` `test`.`t1` ), use_index(@`sel_1` `test`.`t2` ), inl_join(@`sel_1` `test`.`t1`), merge_join(@`sel_1` `test`.`t3`)"
      },
      {
        "SQL": "select /*+ TIDB_INLJ(t1) */ t1.b, t2.a from t t1, t t2 where t1.b = t2.a;",
        "Best": "LeftHashJoin{TableReader(Table(t))->IndexReader(Index(t.f)[[NULL,+inf]])}(test.t.b,test.t.a)",
        "Warning": "[planner:1815]Optimizer Hint /*+ INL_JOIN(t1) */ or /*+ TIDB_INLJ(t1) */ is inapplicable",
        "Hints": "use_index(@`sel_1` `test`.`t1` ), use_index(@`sel_1` `test`.`t2` `f`), hash_join(@`sel_1` `test`.`t1`)"
      },
      {
        "SQL": "select /*+ TIDB_INLJ(t2) */ t1.b, t2.a from t2 t1, t2 t2 where t1.b=t2.b and t2.c=-1;",
        "Best": "IndexJoin{IndexReader(Index(t2.b)[[NULL,NULL]])->TableReader(Table(t2)->Sel([eq(test.t2.c, -1)]))}(test.t2.b,test.t2.b)",
        "Warning": "[planner:1815]Optimizer Hint /*+ INL_JOIN(t2) */ or /*+ TIDB_INLJ(t2) */ is inapplicable",
        "Hints": "use_index(@`sel_1` `test`.`t1` `b`), use_index(@`sel_1` `test`.`t2` ), inl_join(@`sel_1` `test`.`t1`)"
      }
    ]
  },
  {
    "Name": "TestAggregationHints",
    "Cases": [
      {
        "SQL": "select count(*) from t t1, t t2 where t1.a = t2.b",
        "Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->TableReader(Table(t))}(test.t.a,test.t.b)->StreamAgg",
        "Warning": ""
      },
      {
        "SQL": "select count(t1.a) from t t1, t t2 where t1.a = t2.a*2 group by t1.a",
        "Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.f)[[NULL,+inf]])->Projection}(test.t.a,Column#26)->HashAgg",
        "Warning": ""
      },
      {
        "SQL": "select /*+ HASH_AGG() */ count(*) from t t1, t t2 where t1.a = t2.b",
        "Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->TableReader(Table(t))}(test.t.a,test.t.b)->HashAgg",
        "Warning": ""
      },
      {
        "SQL": "select /*+ STREAM_AGG() */ count(t1.a) from t t1, t t2 where t1.a = t2.a*2 group by t1.a",
        "Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.f)[[NULL,+inf]])->Projection}(test.t.a,Column#26)->Sort->StreamAgg",
        "Warning": ""
      },
      {
        "SQL": "select /*+ HASH_AGG() STREAM_AGG() */ count(*) from t t1, t t2 where t1.a = t2.b",
        "Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->TableReader(Table(t))}(test.t.a,test.t.b)->StreamAgg",
        "Warning": "[planner:1815]Optimizer aggregation hints are conflicted"
      },
      {
        "SQL": "select /*+ STREAM_AGG() */ distinct a from t",
        "Best": "IndexReader(Index(t.f)[[NULL,+inf]])",
        "Warning": ""
      },
      {
        "SQL": "select /*+ HASH_AGG() */ t1.a from t t1 where t1.a < any(select t2.b from t t2)",
        "Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->TableReader(Table(t)->HashAgg)->HashAgg->Sel([ne(Column#27, 0)])}",
        "Warning": ""
      },
      {
        "SQL": "select /*+ hash_agg() */ t1.a from t t1 where t1.a != any(select t2.b from t t2)",
        "Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->TableReader(Table(t))->HashAgg->Sel([ne(Column#28, 0)])}",
        "Warning": ""
      },
      {
        "SQL": "select /*+ hash_agg() */ t1.a from t t1 where t1.a = all(select t2.b from t t2)",
        "Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->TableReader(Table(t))->HashAgg->Sel([or(and(le(Column#26, 1), if(ne(Column#27, 0), <nil>, 1)), or(eq(Column#28, 0), 0))])}",
        "Warning": ""
      },
      {
        "SQL": "select /*+ STREAM_AGG() */ sum(t1.a) from t t1 join t t2 on t1.b = t2.b group by t1.b",
        "Best": "LeftHashJoin{TableReader(Table(t))->TableReader(Table(t))->Sort->Projection->StreamAgg}(test.t.b,test.t.b)->HashAgg",
        "Warning": ""
      },
      {
        "SQL": "select /*+ STREAM_AGG() */ e, sum(b) from t group by e",
        "Best": "TableReader(Table(t))->Sort->Projection->StreamAgg->Projection",
        "Warning": ""
      }
    ]
  },
  {
    "Name": "TestQueryBlockHint",
    "Cases": [
      {
        "SQL": "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",
        "Plan": "MergeInnerJoin{TableReader(Table(t))->IndexJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,NULL]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)",
        "Hints": "use_index(@`sel_1` `test`.`t1` ), use_index(@`sel_2` `test`.`t2` ), use_index(@`sel_2` `test`.`t3` `c_d_e`), inl_join(@`sel_2` `test`.`t3`), merge_join(@`sel_1` `test`.`t1`)"
      },
      {
        "SQL": "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",
        "Plan": "MergeInnerJoin{TableReader(Table(t))->IndexJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,NULL]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)",
        "Hints": "use_index(@`sel_1` `test`.`t1` ), use_index(@`sel_2` `test`.`t2` ), use_index(@`sel_2` `test`.`t3` `c_d_e`), inl_join(@`sel_2` `test`.`t3`), merge_join(@`sel_1` `test`.`t1`)"
      },
      {
        "SQL": "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",
        "Plan": "RightHashJoin{TableReader(Table(t))->MergeInnerJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)",
        "Hints": "use_index(@`sel_1` `test`.`t1` ), use_index(@`sel_2` `test`.`t2` ), use_index(@`sel_2` `test`.`t3` `c_d_e`), merge_join(@`sel_2` `test`.`t2`), hash_join(@`sel_1` `test`.`t1`)"
      },
      {
        "SQL": "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",
        "Plan": "RightHashJoin{TableReader(Table(t))->MergeInnerJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)",
        "Hints": "use_index(@`sel_1` `test`.`t1` ), use_index(@`sel_2` `test`.`t2` ), use_index(@`sel_2` `test`.`t3` `c_d_e`), merge_join(@`sel_2` `test`.`t2`), hash_join(@`sel_1` `test`.`t1`)"
      },
      {
        "SQL": "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",
        "Plan": "IndexJoin{TableReader(Table(t))->LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)",
        "Hints": "use_index(@`sel_1` `test`.`t1` ), use_index(@`sel_2` `test`.`t2` `f`), use_index(@`sel_2` `test`.`t3` `c_d_e`), hash_join(@`sel_2` `test`.`t2`), inl_join(@`sel_1` `test`.`t1`)"
      },
      {
        "SQL": "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",
        "Plan": "IndexJoin{TableReader(Table(t))->LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)",
        "Hints": "use_index(@`sel_1` `test`.`t1` ), use_index(@`sel_2` `test`.`t2` `f`), use_index(@`sel_2` `test`.`t3` `c_d_e`), hash_join(@`sel_2` `test`.`t2`), inl_join(@`sel_1` `test`.`t1`)"
      },
      {
        "SQL": "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)",
        "Plan": "Apply{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.f)[[NULL,+inf]]->Sel([gt(test.t.a, test.t.a)])->StreamAgg)->StreamAgg}->HashAgg",
        "Hints": "use_index(@`sel_1` `test`.`t1` `f`), use_index(@`sel_2` `test`.`t2` `f`), stream_agg(@`sel_2`), hash_agg(@`sel_1`)"
      },
      {
        "SQL": "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)",
        "Plan": "Apply{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.f)[[NULL,+inf]]->Sel([gt(test.t.a, test.t.a)])->HashAgg)->HashAgg}->StreamAgg",
        "Hints": "use_index(@`sel_1` `test`.`t1` `f`), use_index(@`sel_2` `test`.`t2` `f`), hash_agg(@`sel_2`), stream_agg(@`sel_1`)"
      },
      {
        "SQL": "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)",
        "Plan": "Apply{Apply{TableReader(Table(t))->TableReader(Table(t)->Sel([eq(test.t.b, test.t.a)])->Limit)->Limit}->TableReader(Table(t)->Sel([gt(test.t.b, test.t.a)])->HashAgg)->HashAgg}->Projection",
        "Hints": "use_index(@`sel_1` `test`.`t` ), use_index(@`sel_3` `test`.`t2` ), use_index(@`sel_2` `test`.`t1` ), hash_agg(@`sel_2`)"
      },
      {
        "SQL": "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;",
        "Plan": "RightHashJoin{TableReader(Table(t))->LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.f)[[NULL,+inf]])}}(test.t.a,test.t.a)",
        "Hints": "use_index(@`sel_1` `test`.`t1` ), use_index(@`sel_2` `test`.`t1` `f`), use_index(@`sel_2` `test`.`t2` `f`), hash_join(@`sel_2` `test`.`t1`), hash_join(@`sel_1` `test`.`t1`)"
      },
      {
        "SQL": "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",
        "Plan": "MergeInnerJoin{LeftHashJoin{TableReader(Table(t))->IndexReader(Index(t.f)[[NULL,+inf]])}(test.t.a,test.t.a)->Sort->TableReader(Table(t))->Sort}(test.t.b,test.t.b)",
        "Hints": "use_index(@`sel_2` `test`.`t1` ), use_index(@`sel_2` `test`.`t2` `f`), hash_join(@`sel_2` `test`.`t1`), use_index(@`sel_1` `test`.`t2` ), merge_join(@`sel_1` `test`.`t1`)"
      }
    ]
  },
  {
    "Name": "TestIndexJoinUnionScan",
    "Cases": [
      {
        "SQL": [
          "insert into t values(1, 1)",
          "explain format = 'brief' select /*+ TIDB_INLJ(t2) */ * from t t1, t t2 where t1.a = t2.a"
        ],
        "Plan": [
          "IndexJoin 12500.00 root  inner join, inner:UnionScan, outer key:test.t.a, inner key:test.t.a, equal cond:eq(test.t.a, test.t.a)",
          "├─UnionScan(Build) 10000.00 root  ",
          "│ └─TableReader 10000.00 root  data:TableFullScan",
          "│   └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─UnionScan(Probe) 10000.00 root  ",
          "  └─TableReader 10000.00 root  data:TableRangeScan",
          "    └─TableRangeScan 10000.00 cop[tikv] table:t2 range: decided by [test.t.a], keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": [
          "insert into t values(1, 1)",
          "explain format = 'brief' select /*+ TIDB_INLJ(t2) */ * from t t1, t t2 where t1.a = t2.b"
        ],
        "Plan": [
          "HashJoin 12487.50 root  inner join, equal:[eq(test.t.a, test.t.b)]",
          "├─UnionScan(Build) 9990.00 root  not(isnull(test.t.b))",
          "│ └─TableReader 9990.00 root  data:Selection",
          "│   └─Selection 9990.00 cop[tikv]  not(isnull(test.t.b))",
          "│     └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─UnionScan(Probe) 10000.00 root  ",
          "  └─TableReader 10000.00 root  data:TableFullScan",
          "    └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": [
          "insert into t values(1, 1)",
          "explain format = 'brief' select /*+ TIDB_INLJ(t2) */ t1.a , t2.b from t t1, t t2 where t1.a = t2.b"
        ],
        "Plan": [
          "HashJoin 12487.50 root  inner join, equal:[eq(test.t.a, test.t.b)]",
          "├─UnionScan(Build) 10000.00 root  ",
          "│ └─TableReader 10000.00 root  data:TableFullScan",
          "│   └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─UnionScan(Probe) 9990.00 root  not(isnull(test.t.b))",
          "  └─TableReader 9990.00 root  data:Selection",
          "    └─Selection 9990.00 cop[tikv]  not(isnull(test.t.b))",
          "      └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": [
          "insert into tt values(1)",
          "explain format = 'brief' select /*+ TIDB_INLJ(t2) */ * from tt t1, tt t2 where t1.a = t2.a"
        ],
        "Plan": [
          "HashJoin 25000.00 root  inner join, equal:[eq(test.tt.a, test.tt.a)]",
          "├─PartitionUnion(Build) 20000.00 root  ",
          "│ ├─UnionScan 10000.00 root  ",
          "│ │ └─TableReader 10000.00 root  data:TableFullScan",
          "│ │   └─TableFullScan 10000.00 cop[tikv] table:t2, partition:p0 keep order:false, stats:pseudo",
          "│ └─UnionScan 10000.00 root  ",
          "│   └─TableReader 10000.00 root  data:TableFullScan",
          "│     └─TableFullScan 10000.00 cop[tikv] table:t2, partition:p1 keep order:false, stats:pseudo",
          "└─PartitionUnion(Probe) 20000.00 root  ",
          "  ├─UnionScan 10000.00 root  ",
          "  │ └─TableReader 10000.00 root  data:TableFullScan",
          "  │   └─TableFullScan 10000.00 cop[tikv] table:t1, partition:p0 keep order:false, stats:pseudo",
          "  └─UnionScan 10000.00 root  ",
          "    └─TableReader 10000.00 root  data:TableFullScan",
          "      └─TableFullScan 10000.00 cop[tikv] table:t1, partition:p1 keep order:false, stats:pseudo"
        ]
      }
    ]
  },
  {
    "Name": "TestMergeJoinUnionScan",
    "Cases": [
      {
        "SQL": [
          "insert into t2 values (11, 'amazing merkle')",
          "insert into t2 values (12, 'amazing merkle')",
          "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;"
        ],
        "Plan": [
          "Sort 12500.00 root  test.t1.c_int, test.t2.c_str",
          "└─MergeJoin 12500.00 root  inner join, left key:test.t1.c_int, right key:test.t2.c_int",
          "  ├─UnionScan(Build) 10000.00 root  ",
          "  │ └─TableReader 10000.00 root  data:TableFullScan",
          "  │   └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo",
          "  └─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "    └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo"
        ]
      }
    ]
  },
  {
    "Name": "TestSemiJoinToInner",
    "Cases": [
      {
        "SQL": "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;",
        "Best": "Apply{IndexReader(Index(t.f)[[NULL,+inf]])->IndexHashJoin{IndexReader(Index(t.c_d_e)[[NULL,+inf]]->HashAgg)->HashAgg->IndexReader(Index(t.g)[[NULL,NULL]])}(test.t.d,test.t.g)}->HashAgg"
      }
    ]
  },
  {
    "Name": "TestIndexJoinHint",
    "Cases": [
      {
        "SQL": "select /*+ INL_JOIN(t1) */ * from t1 join t2 on t1.a = t2.a;",
        "Plan": "IndexJoin{IndexLookUp(Index(t1.idx_a)[[NULL,NULL]]->Sel([not(isnull(test.t1.a))]), Table(t1))->TableReader(Table(t2)->Sel([not(isnull(test.t2.a))]))}(test.t2.a,test.t1.a)"
      },
      {
        "SQL": "select /*+ INL_HASH_JOIN(t1) */ * from t1 join t2 on t1.a = t2.a;",
        "Plan": "IndexHashJoin{IndexLookUp(Index(t1.idx_a)[[NULL,NULL]]->Sel([not(isnull(test.t1.a))]), Table(t1))->TableReader(Table(t2)->Sel([not(isnull(test.t2.a))]))}(test.t2.a,test.t1.a)"
      },
      {
        "SQL": "select /*+ INL_MERGE_JOIN(t1) */ * from t1 join t2 on t1.a = t2.a;",
        "Plan": "IndexMergeJoin{IndexLookUp(Index(t1.idx_a)[[NULL,NULL]]->Sel([not(isnull(test.t1.a))]), Table(t1))->Projection->TableReader(Table(t2)->Sel([not(isnull(test.t2.a))]))}(test.t2.a,test.t1.a)"
      },
      {
        "SQL": "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",
        "Plan": "IndexMergeJoin{IndexReader(Index(t.g_2)[[NULL,+inf]])->IndexReader(Index(t.g_2)[[NULL,NULL]]->Sel([not(isnull(test.t.g))]))}(test.t.g,test.t.g)"
      },
      {
        "SQL": "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",
        "Plan": "IndexMergeJoin{IndexReader(Index(t.g_2)[[NULL,+inf]])->IndexReader(Index(t.g_2)[[NULL,NULL]]->Sel([not(isnull(test.t.g))]))}(test.t.g,test.t.g)->Sort"
      }
    ]
  },
  {
    "Name": "TestAggToCopHint",
    "Cases": [
      {
        "SQL": "select /*+ AGG_TO_COP(), HASH_AGG(), USE_INDEX(t) */ sum(a) from ta group by a",
        "Best": "IndexReader(Index(ta.a)[[NULL,+inf]]->HashAgg)->HashAgg",
        "Warning": "[planner:1815]use_index(test.t) is inapplicable, check whether the table(test.t) exists"
      },
      {
        "SQL": "select /*+ AGG_TO_COP(), USE_INDEX(t) */ sum(b) from ta group by b",
        "Best": "TableReader(Table(ta)->HashAgg)->HashAgg",
        "Warning": "[planner:1815]use_index(test.t) is inapplicable, check whether the table(test.t) exists"
      },
      {
        "SQL": "select /*+ AGG_TO_COP(), HASH_AGG(), USE_INDEX(t) */ distinct a from ta group by a",
        "Best": "IndexReader(Index(ta.a)[[NULL,+inf]]->HashAgg)->HashAgg",
        "Warning": "[planner:1815]use_index(test.t) is inapplicable, check whether the table(test.t) exists"
      },
      {
        "SQL": "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",
        "Best": "LeftHashJoin{TableReader(Table(ta)->Sel([not(isnull(test.ta.a))]))->TableReader(Table(ta)->Sel([not(isnull(test.ta.b))]))}(test.ta.a,test.ta.b)->Projection->HashAgg",
        "Warning": "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable"
      }
    ]
  },
  {
    "Name": "TestLimitToCopHint",
    "Cases": [
      {
        "SQL": "select /*+ LIMIT_TO_COP() */ * from tn where a = 1 and b > 10 and b < 20 and c > 50 order by d limit 1",
        "Plan": [
          "TopN 0.83 root  test.tn.d, offset:0, count:1",
          "└─IndexReader 0.83 root  index:TopN",
          "  └─TopN 0.83 cop[tikv]  test.tn.d, offset:0, count:1",
          "    └─Selection 0.83 cop[tikv]  gt(test.tn.c, 50)",
          "      └─IndexRangeScan 2.50 cop[tikv] table:tn, index:a(a, b, c, d) range:(1 10,1 20), keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "select * from tn where a = 1 and b > 10 and b < 20 and c > 50 order by d limit 1",
        "Plan": [
          "TopN 0.83 root  test.tn.d, offset:0, count:1",
          "└─IndexReader 0.83 root  index:TopN",
          "  └─TopN 0.83 cop[tikv]  test.tn.d, offset:0, count:1",
          "    └─Selection 0.83 cop[tikv]  gt(test.tn.c, 50)",
          "      └─IndexRangeScan 2.50 cop[tikv] table:tn, index:a(a, b, c, d) range:(1 10,1 20), keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ LIMIT_TO_COP() */ a from tn where a div 2 order by a limit 1",
        "Plan": [
          "Limit 1.00 root  offset:0, count:1",
          "└─Selection 1.00 root  intdiv(test.tn.a, 2)",
          "  └─IndexReader 1.00 root  index:IndexFullScan",
          "    └─IndexFullScan 1.00 cop[tikv] table:tn, index:a(a, b, c, d) keep order:true, stats:pseudo"
        ],
        "Warning": [
          "Scalar function 'intdiv'(signature: IntDivideInt, return type: bigint(20)) is not supported to push down to storage layer now.",
          "[planner:1815]Optimizer Hint LIMIT_TO_COP is inapplicable"
        ]
      },
      {
        "SQL": "select /*+ LIMIT_TO_COP() */ a from tn where a > 10 limit 1",
        "Plan": [
          "Limit 1.00 root  offset:0, count:1",
          "└─IndexReader 1.00 root  index:Limit",
          "  └─Limit 1.00 cop[tikv]  offset:0, count:1",
          "    └─IndexRangeScan 1.00 cop[tikv] table:tn, index:a(a, b, c, d) range:(10,+inf], keep order:false, stats:pseudo"
        ],
        "Warning": null
      }
    ]
  },
  {
    "Name": "TestCTEMergeHint",
    "Cases": [
      {
        "SQL": "with cte as (select /*+ MERGE() */ * from tc where tc.a < 60) select * from cte where cte.a <18",
        "Plan": [
          "TableReader 4.00 root  data:Selection",
          "└─Selection 4.00 cop[tikv]  lt(test.tc.a, 18), lt(test.tc.a, 60)",
          "  └─TableFullScan 7.00 cop[tikv] table:tc keep order:false"
        ],
        "Warning": null
      },
      {
        "SQL": "with cte as (select * from tc where tc.a < 60) select * from cte c1, cte c2 where c1.a <18",
        "Plan": [
          "Projection 39.20 root  test.tc.a, test.tc.a",
          "└─HashJoin 39.20 root  CARTESIAN inner join",
          "  ├─Selection(Build) 5.60 root  lt(test.tc.a, 18)",
          "  │ └─CTEFullScan 7.00 root CTE:cte AS c1 data:CTE_0",
          "  └─CTEFullScan(Probe) 7.00 root CTE:cte AS c2 data:CTE_0",
          "CTE_0 7.00 root  Non-Recursive CTE",
          "└─TableReader(Seed Part) 7.00 root  data:Selection",
          "  └─Selection 7.00 cop[tikv]  lt(test.tc.a, 60), or(lt(test.tc.a, 18), 1)",
          "    └─TableFullScan 7.00 cop[tikv] table:tc keep order:false"
        ],
        "Warning": null
      },
      {
        "SQL": "with cte as (select /*+ MERGE() */ * from v) select * from cte",
        "Plan": [
          "TableReader 7.00 root  data:TableFullScan",
          "└─TableFullScan 7.00 cop[tikv] table:tc keep order:false"
        ],
        "Warning": null
      },
      {
        "SQL": "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;",
        "Plan": [
          "HashJoin 7.00 root  inner join, equal:[eq(test.tc.a, test.te.c)]",
          "├─TableReader(Build) 7.00 root  data:Selection",
          "│ └─Selection 7.00 cop[tikv]  not(isnull(test.te.c))",
          "│   └─TableFullScan 7.00 cop[tikv] table:te keep order:false",
          "└─TableReader(Probe) 7.00 root  data:Selection",
          "  └─Selection 7.00 cop[tikv]  not(isnull(test.tc.a))",
          "    └─TableFullScan 7.00 cop[tikv] table:tc keep order:false"
        ],
        "Warning": null
      },
      {
        "SQL": "WITH cte1 AS (SELECT a FROM tc), cte2 AS (SELECT /*+ MERGE() */ c FROM te) SELECT * FROM cte1 JOIN cte2 WHERE cte1.a = cte2.c;",
        "Plan": [
          "HashJoin 7.00 root  inner join, equal:[eq(test.tc.a, test.te.c)]",
          "├─TableReader(Build) 7.00 root  data:Selection",
          "│ └─Selection 7.00 cop[tikv]  not(isnull(test.te.c))",
          "│   └─TableFullScan 7.00 cop[tikv] table:te keep order:false",
          "└─TableReader(Probe) 7.00 root  data:Selection",
          "  └─Selection 7.00 cop[tikv]  not(isnull(test.tc.a))",
          "    └─TableFullScan 7.00 cop[tikv] table:tc keep order:false"
        ],
        "Warning": null
      },
      {
        "SQL": "with recursive cte1(c1) as (select 1 union select /*+ MERGE() */ c1 + 1 c1 from cte1 where c1 < 100) select * from cte1;",
        "Plan": [
          "CTEFullScan 2.00 root CTE:cte1 data:CTE_0",
          "CTE_0 2.00 root  Recursive CTE",
          "├─Projection(Seed Part) 1.00 root  1->Column#2",
          "│ └─TableDual 1.00 root  rows:1",
          "└─Projection(Recursive Part) 0.80 root  cast(plus(Column#3, 1), bigint(1) BINARY)->Column#5",
          "  └─Selection 0.80 root  lt(Column#3, 100)",
          "    └─CTETable 1.00 root  Scan on CTE_0"
        ],
        "Warning": [
          "[planner:1815]Recursive CTE can not be inlined."
        ]
      },
      {
        "SQL": "WITH cte1 AS (SELECT * FROM t1) SELECT /*+ MERGE() */ * FROM cte1 join t2 on cte1.a = t2.b;",
        "Plan": [
          "HashJoin 7.00 root  inner join, equal:[eq(test.t1.a, test.t2.b)]",
          "├─TableReader(Build) 7.00 root  data:Selection",
          "│ └─Selection 7.00 cop[tikv]  not(isnull(test.t2.b))",
          "│   └─TableFullScan 7.00 cop[tikv] table:t2 keep order:false",
          "└─TableReader(Probe) 7.00 root  data:Selection",
          "  └─Selection 7.00 cop[tikv]  not(isnull(test.t1.a))",
          "    └─TableFullScan 7.00 cop[tikv] table:t1 keep order:false"
        ],
        "Warning": [
          "[planner:1815]Hint merge() is inapplicable. Please check whether the hint is used in the right place, you should use this hint inside the CTE."
        ]
      },
      {
        "SQL": "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;",
        "Plan": [
          "HashJoin 343.00 root  CARTESIAN inner join",
          "├─TableReader(Build) 7.00 root  data:TableFullScan",
          "│ └─TableFullScan 7.00 cop[tikv] table:t3 keep order:false",
          "└─HashJoin(Probe) 49.00 root  CARTESIAN inner join",
          "  ├─TableReader(Build) 7.00 root  data:TableFullScan",
          "  │ └─TableFullScan 7.00 cop[tikv] table:t2 keep order:false",
          "  └─TableReader(Probe) 7.00 root  data:TableFullScan",
          "    └─TableFullScan 7.00 cop[tikv] table:t1 keep order:false"
        ],
        "Warning": null
      },
      {
        "SQL": "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;",
        "Plan": [
          "HashJoin 49.00 root  CARTESIAN inner join",
          "├─TableReader(Build) 7.00 root  data:TableFullScan",
          "│ └─TableFullScan 7.00 cop[tikv] table:tc keep order:false",
          "└─TableReader(Probe) 7.00 root  data:TableFullScan",
          "  └─TableFullScan 7.00 cop[tikv] table:te keep order:false"
        ],
        "Warning": null
      },
      {
        "SQL": "with cte1 as (with cte2 as (select /*+ MERGE() */ * from te) ,cte3 as (select /*+ MERGE() */ * from tc) select /*+ MERGE() */ * from cte2,cte3) select * from cte1;",
        "Plan": [
          "HashJoin 49.00 root  CARTESIAN inner join",
          "├─TableReader(Build) 7.00 root  data:TableFullScan",
          "│ └─TableFullScan 7.00 cop[tikv] table:tc keep order:false",
          "└─TableReader(Probe) 7.00 root  data:TableFullScan",
          "  └─TableFullScan 7.00 cop[tikv] table:te keep order:false"
        ],
        "Warning": null
      },
      {
        "SQL": "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;",
        "Plan": [
          "HashJoin 2401.00 root  CARTESIAN inner join",
          "├─HashJoin(Build) 49.00 root  CARTESIAN inner join",
          "│ ├─TableReader(Build) 7.00 root  data:TableFullScan",
          "│ │ └─TableFullScan 7.00 cop[tikv] table:t4 keep order:false",
          "│ └─TableReader(Probe) 7.00 root  data:TableFullScan",
          "│   └─TableFullScan 7.00 cop[tikv] table:t3 keep order:false",
          "└─HashJoin(Probe) 49.00 root  CARTESIAN inner join",
          "  ├─TableReader(Build) 7.00 root  data:TableFullScan",
          "  │ └─TableFullScan 7.00 cop[tikv] table:t2 keep order:false",
          "  └─TableReader(Probe) 7.00 root  data:TableFullScan",
          "    └─TableFullScan 7.00 cop[tikv] table:t1 keep order:false"
        ],
        "Warning": null
      },
      {
        "SQL": "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;",
        "Plan": [
          "HashJoin 2401.00 root  CARTESIAN inner join",
          "├─HashJoin(Build) 49.00 root  CARTESIAN inner join",
          "│ ├─TableReader(Build) 7.00 root  data:TableFullScan",
          "│ │ └─TableFullScan 7.00 cop[tikv] table:t4 keep order:false",
          "│ └─TableReader(Probe) 7.00 root  data:TableFullScan",
          "│   └─TableFullScan 7.00 cop[tikv] table:t3 keep order:false",
          "└─HashJoin(Probe) 49.00 root  CARTESIAN inner join",
          "  ├─TableReader(Build) 7.00 root  data:TableFullScan",
          "  │ └─TableFullScan 7.00 cop[tikv] table:t2 keep order:false",
          "  └─TableReader(Probe) 7.00 root  data:TableFullScan",
          "    └─TableFullScan 7.00 cop[tikv] table:t1 keep order:false"
        ],
        "Warning": null
      },
      {
        "SQL": "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;",
        "Plan": [
          "HashJoin 2401.00 root  CARTESIAN inner join",
          "├─HashJoin(Build) 49.00 root  CARTESIAN inner join",
          "│ ├─TableReader(Build) 7.00 root  data:TableFullScan",
          "│ │ └─TableFullScan 7.00 cop[tikv] table:t4 keep order:false",
          "│ └─TableReader(Probe) 7.00 root  data:TableFullScan",
          "│   └─TableFullScan 7.00 cop[tikv] table:t3 keep order:false",
          "└─HashJoin(Probe) 49.00 root  CARTESIAN inner join",
          "  ├─TableReader(Build) 7.00 root  data:TableFullScan",
          "  │ └─TableFullScan 7.00 cop[tikv] table:t2 keep order:false",
          "  └─TableReader(Probe) 7.00 root  data:TableFullScan",
          "    └─TableFullScan 7.00 cop[tikv] table:t1 keep order:false"
        ],
        "Warning": null
      },
      {
        "SQL": "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;",
        "Plan": [
          "HashJoin 2401.00 root  CARTESIAN inner join",
          "├─HashJoin(Build) 49.00 root  CARTESIAN inner join",
          "│ ├─TableReader(Build) 7.00 root  data:TableFullScan",
          "│ │ └─TableFullScan 7.00 cop[tikv] table:t4 keep order:false",
          "│ └─TableReader(Probe) 7.00 root  data:TableFullScan",
          "│   └─TableFullScan 7.00 cop[tikv] table:t3 keep order:false",
          "└─HashJoin(Probe) 49.00 root  CARTESIAN inner join",
          "  ├─TableReader(Build) 7.00 root  data:TableFullScan",
          "  │ └─TableFullScan 7.00 cop[tikv] table:t2 keep order:false",
          "  └─TableReader(Probe) 7.00 root  data:TableFullScan",
          "    └─TableFullScan 7.00 cop[tikv] table:t1 keep order:false"
        ],
        "Warning": null
      },
      {
        "SQL": "with cte2 as (with cte4 as (select * from tc) select * from te, cte4) select * from cte2;",
        "Plan": [
          "HashJoin 49.00 root  CARTESIAN inner join",
          "├─TableReader(Build) 7.00 root  data:TableFullScan",
          "│ └─TableFullScan 7.00 cop[tikv] table:tc keep order:false",
          "└─TableReader(Probe) 7.00 root  data:TableFullScan",
          "  └─TableFullScan 7.00 cop[tikv] table:te keep order:false"
        ],
        "Warning": null
      },
      {
        "SQL": "with cte2 as (with cte4 as (select /*+ merge() */ * from tc) select * from te, cte4) select * from cte2;",
        "Plan": [
          "HashJoin 49.00 root  CARTESIAN inner join",
          "├─TableReader(Build) 7.00 root  data:TableFullScan",
          "│ └─TableFullScan 7.00 cop[tikv] table:tc keep order:false",
          "└─TableReader(Probe) 7.00 root  data:TableFullScan",
          "  └─TableFullScan 7.00 cop[tikv] table:te keep order:false"
        ],
        "Warning": null
      },
      {
        "SQL": "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;",
        "Plan": [
          "HashJoin 49.00 root  CARTESIAN inner join",
          "├─TableReader(Build) 7.00 root  data:TableFullScan",
          "│ └─TableFullScan 7.00 cop[tikv] table:t1 keep order:false",
          "└─TableReader(Probe) 7.00 root  data:TableFullScan",
          "  └─TableFullScan 7.00 cop[tikv] table:t2 keep order:false"
        ],
        "Warning": [
          "[planner:1815]Hint merge() is inapplicable. Please check whether the hint is used in the right place, you should use this hint inside the CTE.",
          "[planner:1815]Hint merge() is inapplicable. Please check whether the hint is used in the right place, you should use this hint inside the CTE."
        ]
      },
      {
        "SQL": "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;",
        "Plan": [
          "HashJoin 343.00 root  CARTESIAN inner join",
          "├─TableReader(Build) 7.00 root  data:TableFullScan",
          "│ └─TableFullScan 7.00 cop[tikv] table:t3 keep order:false",
          "└─HashJoin(Probe) 49.00 root  CARTESIAN inner join",
          "  ├─TableReader(Build) 7.00 root  data:TableFullScan",
          "  │ └─TableFullScan 7.00 cop[tikv] table:t1 keep order:false",
          "  └─TableReader(Probe) 7.00 root  data:TableFullScan",
          "    └─TableFullScan 7.00 cop[tikv] table:t2 keep order:false"
        ],
        "Warning": [
          "[planner:1815]Hint merge() is inapplicable. Please check whether the hint is used in the right place, you should use this hint inside the CTE."
        ]
      },
      {
        "SQL": "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;",
        "Plan": [
          "HashJoin 343.00 root  CARTESIAN inner join",
          "├─TableReader(Build) 7.00 root  data:TableFullScan",
          "│ └─TableFullScan 7.00 cop[tikv] table:t3 keep order:false",
          "└─HashJoin(Probe) 49.00 root  CARTESIAN inner join",
          "  ├─TableReader(Build) 7.00 root  data:TableFullScan",
          "  │ └─TableFullScan 7.00 cop[tikv] table:t1 keep order:false",
          "  └─TableReader(Probe) 7.00 root  data:TableFullScan",
          "    └─TableFullScan 7.00 cop[tikv] table:t2 keep order:false"
        ],
        "Warning": null
      }
    ]
  },
  {
    "Name": "TestForceInlineCTE",
    "Cases": [
      {
        "SQL": "set tidb_opt_force_inline_cte=1; -- enable force inline CTE",
        "Plan": null,
        "Warning": null
      },
      {
        "SQL": "with cte as (select * from t) select * from cte; -- inline",
        "Plan": [
          "TableReader 10000.00 root  data:TableFullScan",
          "└─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "with cte as (select /*+ MERGE() */ * from t) select * from cte; -- inline",
        "Plan": [
          "TableReader 10000.00 root  data:TableFullScan",
          "└─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "with cte as (select * from t) select * from cte cte1, cte cte2; -- inline CTEs is used by multi consumers",
        "Plan": [
          "HashJoin 100000000.00 root  CARTESIAN inner join",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "with cte1 as (select * from t), cte2 as (select a from cte1 group by a) select * from cte1, cte2; -- multi inline CTEs",
        "Plan": [
          "HashJoin 80000000.00 root  CARTESIAN inner join",
          "├─HashAgg(Build) 8000.00 root  group by:test.t.a, funcs:firstrow(test.t.a)->test.t.a",
          "│ └─TableReader 8000.00 root  data:HashAgg",
          "│   └─HashAgg 8000.00 cop[tikv]  group by:test.t.a, ",
          "│     └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "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",
        "Plan": [
          "CTEFullScan 2.00 root CTE:cte1 data:CTE_0",
          "CTE_0 2.00 root  Recursive CTE",
          "├─Projection(Seed Part) 1.00 root  1->Column#2",
          "│ └─TableDual 1.00 root  rows:1",
          "└─Projection(Recursive Part) 0.80 root  cast(plus(Column#3, 1), bigint(1) BINARY)->Column#5",
          "  └─Selection 0.80 root  lt(Column#3, 100)",
          "    └─CTETable 1.00 root  Scan on CTE_0"
        ],
        "Warning": null
      },
      {
        "SQL": "with cte1 as (with cte2 as (select * from t) select * from cte2) select * from cte1; -- non-recursive 'cte2' definition inside another non-recursive 'cte1'",
        "Plan": [
          "TableReader 10000.00 root  data:TableFullScan",
          "└─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "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'",
        "Plan": [
          "CTEFullScan 8001.00 root CTE:cte2 data:CTE_0",
          "CTE_0 8001.00 root  Recursive CTE",
          "├─TableReader(Seed Part) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo",
          "└─Projection(Recursive Part) 8000.00 root  cast(plus(test.t.a, 1), int(11))->test.t.a",
          "  └─Selection 8000.00 root  lt(test.t.a, 100)",
          "    └─CTETable 10000.00 root  Scan on CTE_0"
        ],
        "Warning": null
      },
      {
        "SQL": "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'",
        "Plan": [
          "CTEFullScan 2.00 root CTE:cte2 data:CTE_2",
          "CTE_2 2.00 root  Recursive CTE",
          "├─Projection(Seed Part) 1.00 root  1->Column#9",
          "│ └─TableDual 1.00 root  rows:1",
          "└─Projection(Recursive Part) 0.80 root  cast(plus(Column#10, 1), bigint(1) BINARY)->Column#12",
          "  └─Selection 0.80 root  lt(Column#10, 100)",
          "    └─CTETable 1.00 root  Scan on CTE_2"
        ],
        "Warning": null
      },
      {
        "SQL": "set tidb_opt_force_inline_cte=0; -- disable force inline CTE",
        "Plan": null,
        "Warning": null
      },
      {
        "SQL": "with cte as (select * from t) select * from cte; -- inlined by single consumer",
        "Plan": [
          "TableReader 10000.00 root  data:TableFullScan",
          "└─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "with cte as (select /*+ MERGE() */ * from t) select * from cte; -- inline, merge hint override session variable",
        "Plan": [
          "TableReader 10000.00 root  data:TableFullScan",
          "└─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "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",
        "Plan": [
          "CTEFullScan 2.00 root CTE:cte1 data:CTE_0",
          "CTE_0 2.00 root  Recursive CTE",
          "├─Projection(Seed Part) 1.00 root  1->Column#2",
          "│ └─TableDual 1.00 root  rows:1",
          "└─Projection(Recursive Part) 0.80 root  cast(plus(Column#3, 1), bigint(1) BINARY)->Column#5",
          "  └─Selection 0.80 root  lt(Column#3, 100)",
          "    └─CTETable 1.00 root  Scan on CTE_0"
        ],
        "Warning": [
          "[planner:1815]Recursive CTE can not be inlined."
        ]
      },
      {
        "SQL": "with cte1 as (with cte2 as (select * from t) select * from cte2) select * from cte1; -- non-recursive 'cte2' definition inside another non-recursive 'cte1'",
        "Plan": [
          "TableReader 10000.00 root  data:TableFullScan",
          "└─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "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'",
        "Plan": [
          "CTEFullScan 8001.00 root CTE:cte2 data:CTE_0",
          "CTE_0 8001.00 root  Recursive CTE",
          "├─TableReader(Seed Part) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo",
          "└─Projection(Recursive Part) 8000.00 root  cast(plus(test.t.a, 1), int(11))->test.t.a",
          "  └─Selection 8000.00 root  lt(test.t.a, 100)",
          "    └─CTETable 10000.00 root  Scan on CTE_0"
        ],
        "Warning": null
      },
      {
        "SQL": "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'",
        "Plan": [
          "CTEFullScan 2.00 root CTE:cte2 data:CTE_2",
          "CTE_2 2.00 root  Recursive CTE",
          "├─Projection(Seed Part) 1.00 root  1->Column#9",
          "│ └─TableDual 1.00 root  rows:1",
          "└─Projection(Recursive Part) 0.80 root  cast(plus(Column#10, 1), bigint(1) BINARY)->Column#12",
          "  └─Selection 0.80 root  lt(Column#10, 100)",
          "    └─CTETable 1.00 root  Scan on CTE_2"
        ],
        "Warning": null
      }
    ]
  },
  {
    "Name": "TestSingleConsumerCTE",
    "Cases": [
      {
        "SQL": "with cte as (select 1) select * from cte; -- inline cte",
        "Plan": [
          "Projection 1.00 root  1->Column#3",
          "└─TableDual 1.00 root  rows:1"
        ],
        "Warning": null
      },
      {
        "SQL": "with cte1 as (select 1), cte2 as (select 2) select * from cte1 union select * from cte2; -- inline cte1, cte2",
        "Plan": [
          "HashAgg 2.00 root  group by:Column#7, funcs:firstrow(Column#7)->Column#7",
          "└─Union 2.00 root  ",
          "  ├─Projection 1.00 root  1->Column#7",
          "  │ └─TableDual 1.00 root  rows:1",
          "  └─Projection 1.00 root  2->Column#7",
          "    └─TableDual 1.00 root  rows:1"
        ],
        "Warning": null
      },
      {
        "SQL": "with cte as (select 1) select * from cte union select * from cte; -- cannot be inlined",
        "Plan": [
          "HashAgg 2.00 root  group by:Column#4, funcs:firstrow(Column#4)->Column#4",
          "└─Union 2.00 root  ",
          "  ├─CTEFullScan 1.00 root CTE:cte data:CTE_0",
          "  └─CTEFullScan 1.00 root CTE:cte data:CTE_0",
          "CTE_0 1.00 root  Non-Recursive CTE",
          "└─Projection(Seed Part) 1.00 root  1->Column#1",
          "  └─TableDual 1.00 root  rows:1"
        ],
        "Warning": null
      },
      {
        "SQL": "with cte as (with cte as (select 1) select * from cte) select * from cte; -- inline nested cte",
        "Plan": [
          "Projection 1.00 root  1->Column#7",
          "└─TableDual 1.00 root  rows:1"
        ],
        "Warning": null
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 0.64 root  CARTESIAN inner join",
          "├─CTEFullScan(Build) 0.80 root CTE:cte AS b data:CTE_0",
          "└─CTEFullScan(Probe) 0.80 root CTE:cte AS a data:CTE_0",
          "CTE_0 0.80 root  Non-Recursive CTE",
          "└─Selection(Seed Part) 0.80 root  1",
          "  └─Projection 1.00 root  1->Column#3",
          "    └─TableDual 1.00 root  rows:1"
        ],
        "Warning": null
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 0.64 root  CARTESIAN inner join",
          "├─CTEFullScan(Build) 0.80 root CTE:cte1 data:CTE_0",
          "└─CTEFullScan(Probe) 0.80 root CTE:cte1 data:CTE_0",
          "CTE_0 0.80 root  Non-Recursive CTE",
          "└─Selection(Seed Part) 0.80 root  1",
          "  └─Projection 1.00 root  1->Column#1",
          "    └─TableDual 1.00 root  rows:1"
        ],
        "Warning": null
      },
      {
        "SQL": "with cte1 as (select 1), cte2 as (with cte3 as (select * from cte1) select * from cte3) select * from cte2; -- inline cte1, cte2, cte3",
        "Plan": [
          "Projection 1.00 root  1->Column#12",
          "└─TableDual 1.00 root  rows:1"
        ],
        "Warning": null
      },
      {
        "SQL": "with cte1 as (select 1), cte2 as (select * from cte1) select * from cte2 a, cte2 b; -- inline cte1, cannot be inlined cte2",
        "Plan": [
          "HashJoin 0.64 root  CARTESIAN inner join",
          "├─CTEFullScan(Build) 0.80 root CTE:cte2 AS b data:CTE_1",
          "└─CTEFullScan(Probe) 0.80 root CTE:cte2 AS a data:CTE_1",
          "CTE_1 0.80 root  Non-Recursive CTE",
          "└─Selection(Seed Part) 0.80 root  1",
          "  └─Projection 1.00 root  1->Column#3",
          "    └─TableDual 1.00 root  rows:1"
        ],
        "Warning": null
      },
      {
        "SQL": "with recursive cte(a) as (select 1 union select a from cte) select * from cte; -- recursive cte cannot be inlined",
        "Plan": [
          "CTEFullScan 1.00 root CTE:cte data:CTE_0",
          "CTE_0 1.00 root  Recursive CTE",
          "├─Projection(Seed Part) 1.00 root  1->Column#2",
          "│ └─TableDual 1.00 root  rows:1",
          "└─CTETable(Recursive Part) 1.00 root  Scan on CTE_0"
        ],
        "Warning": null
      },
      {
        "SQL": "with x as (select * from (select a from t for update) s) select * from x where a = 1;",
        "Plan": [
          "Projection 10.00 root  test.t.a",
          "└─SelectLock 10.00 root  for update 0",
          "  └─TableReader 10.00 root  data:Selection",
          "    └─Selection 10.00 cop[tikv]  eq(test.t.a, 1)",
          "      └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "set tidb_opt_force_inline_cte=1; -- enable force inline CTE",
        "Plan": null,
        "Warning": null
      },
      {
        "SQL": "with cte as (select 1) select * from cte union select * from cte; -- force inline cte while multi-consumer",
        "Plan": [
          "HashAgg 2.00 root  group by:Column#6, funcs:firstrow(Column#6)->Column#6",
          "└─Union 2.00 root  ",
          "  ├─Projection 1.00 root  1->Column#6",
          "  │ └─TableDual 1.00 root  rows:1",
          "  └─Projection 1.00 root  1->Column#6",
          "    └─TableDual 1.00 root  rows:1"
        ],
        "Warning": null
      },
      {
        "SQL": "set tidb_opt_force_inline_cte=0; -- disable force inline CTE",
        "Plan": null,
        "Warning": null
      },
      {
        "SQL": "with cte as (select 1) select /*+ MERGE() */ * from cte union select * from cte; -- firstly inline cte, secondly cannot be inlined",
        "Plan": [
          "HashAgg 2.00 root  group by:Column#4, funcs:firstrow(Column#4)->Column#4",
          "└─Union 2.00 root  ",
          "  ├─CTEFullScan 1.00 root CTE:cte data:CTE_0",
          "  └─CTEFullScan 1.00 root CTE:cte data:CTE_0",
          "CTE_0 1.00 root  Non-Recursive CTE",
          "└─Projection(Seed Part) 1.00 root  1->Column#1",
          "  └─TableDual 1.00 root  rows:1"
        ],
        "Warning": null
      }
    ]
  },
  {
    "Name": "TestPushdownDistinctEnable",
    "Cases": [
      {
        "SQL": "select /*+ HASH_AGG() */ avg(distinct a) from t;",
        "Plan": [
          "HashAgg 1.00 root  funcs:avg(distinct Column#6)->Column#5",
          "└─Projection 1.00 root  cast(test.t.a, decimal(10,0) BINARY)->Column#6",
          "  └─TableReader 1.00 root  data:HashAgg",
          "    └─HashAgg 1.00 cop[tikv]  group by:test.t.a, ",
          "      └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Result": [
          "1.5000"
        ]
      },
      {
        "SQL": "select /*+ HASH_AGG() */ a, count(distinct a) from t;",
        "Plan": [
          "Projection 1.00 root  test.t.a, Column#5",
          "└─HashAgg 1.00 root  funcs:count(distinct test.t.a)->Column#5, funcs:firstrow(Column#6)->test.t.a",
          "  └─TableReader 1.00 root  data:HashAgg",
          "    └─HashAgg 1.00 cop[tikv]  group by:test.t.a, funcs:firstrow(test.t.a)->Column#6",
          "      └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 2"
        ]
      },
      {
        "SQL": "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;",
        "Plan": [
          "Projection 8000.00 root  Column#5, test.t.c, Column#5, Column#6, Column#7, Column#8, Column#9",
          "└─HashAgg 8000.00 root  group by:test.t.c, funcs:avg(Column#10, Column#11)->Column#5, funcs:count(distinct test.t.a, test.t.b)->Column#6, funcs:count(distinct test.t.a)->Column#7, funcs:count(distinct test.t.c)->Column#8, funcs:sum(Column#12)->Column#9, funcs:firstrow(test.t.c)->test.t.c",
          "  └─TableReader 8000.00 root  data:HashAgg",
          "    └─HashAgg 8000.00 cop[tikv]  group by:test.t.a, test.t.b, test.t.c, funcs:count(test.t.b)->Column#10, funcs:sum(test.t.b)->Column#11, funcs:sum(test.t.b)->Column#12",
          "      └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Result": [
          "1.0000 1 1.0000 1 1 1 1",
          "1.3333 3 1.3333 3 2 1 4",
          "2.0000 <nil> 2.0000 1 1 0 2"
        ]
      },
      {
        "SQL": "select /*+ STREAM_AGG() */ count(distinct c) from t group by c;",
        "Plan": [
          "StreamAgg 8000.00 root  group by:test.t.c, funcs:count(distinct test.t.c)->Column#5",
          "└─IndexReader 8000.00 root  index:StreamAgg",
          "  └─StreamAgg 8000.00 cop[tikv]  group by:test.t.c, ",
          "    └─IndexFullScan 10000.00 cop[tikv] table:t, index:c(c) keep order:true, stats:pseudo"
        ],
        "Result": [
          "0",
          "1",
          "1"
        ]
      },
      {
        "SQL": "select /*+ STREAM_AGG() */ count(distinct c) from t;",
        "Plan": [
          "StreamAgg 1.00 root  funcs:count(distinct test.t.c)->Column#5",
          "└─IndexReader 10000.00 root  index:IndexFullScan",
          "  └─IndexFullScan 10000.00 cop[tikv] table:t, index:c(c) keep order:false, stats:pseudo"
        ],
        "Result": [
          "2"
        ]
      },
      {
        "SQL": "select /*+ HASH_AGG() */ count(distinct c) from t;",
        "Plan": [
          "HashAgg 1.00 root  funcs:count(distinct test.t.c)->Column#5",
          "└─IndexReader 1.00 root  index:HashAgg",
          "  └─HashAgg 1.00 cop[tikv]  group by:test.t.c, ",
          "    └─IndexFullScan 10000.00 cop[tikv] table:t, index:c(c) keep order:false, stats:pseudo"
        ],
        "Result": [
          "2"
        ]
      },
      {
        "SQL": "select count(distinct c) from t group by c;",
        "Plan": [
          "StreamAgg 8000.00 root  group by:test.t.c, funcs:count(distinct test.t.c)->Column#5",
          "└─IndexReader 8000.00 root  index:StreamAgg",
          "  └─StreamAgg 8000.00 cop[tikv]  group by:test.t.c, ",
          "    └─IndexFullScan 10000.00 cop[tikv] table:t, index:c(c) keep order:true, stats:pseudo"
        ],
        "Result": [
          "0",
          "1",
          "1"
        ]
      },
      {
        "SQL": "select count(distinct c) from t;",
        "Plan": [
          "HashAgg 1.00 root  funcs:count(distinct test.t.c)->Column#5",
          "└─IndexReader 1.00 root  index:HashAgg",
          "  └─HashAgg 1.00 cop[tikv]  group by:test.t.c, ",
          "    └─IndexFullScan 10000.00 cop[tikv] table:t, index:c(c) keep order:false, stats:pseudo"
        ],
        "Result": [
          "2"
        ]
      },
      {
        "SQL": "select /*+ HASH_AGG(), AGG_TO_COP() */ sum(distinct b) from pt;",
        "Plan": [
          "HashAgg 1.00 root  funcs:sum(distinct Column#9)->Column#4",
          "└─Projection 16000.00 root  cast(test.pt.b, decimal(10,0) BINARY)->Column#9",
          "  └─PartitionUnion 16000.00 root  ",
          "    ├─HashAgg 8000.00 root  group by:test.pt.b, funcs:firstrow(test.pt.b)->test.pt.b, funcs:firstrow(test.pt.b)->test.pt.b",
          "    │ └─TableReader 8000.00 root  data:HashAgg",
          "    │   └─HashAgg 8000.00 cop[tikv]  group by:test.pt.b, ",
          "    │     └─TableFullScan 10000.00 cop[tikv] table:pt, partition:p0 keep order:false, stats:pseudo",
          "    └─HashAgg 8000.00 root  group by:test.pt.b, funcs:firstrow(test.pt.b)->test.pt.b, funcs:firstrow(test.pt.b)->test.pt.b",
          "      └─TableReader 8000.00 root  data:HashAgg",
          "        └─HashAgg 8000.00 cop[tikv]  group by:test.pt.b, ",
          "          └─TableFullScan 10000.00 cop[tikv] table:pt, partition:p1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "<nil>"
        ]
      },
      {
        "SQL": "select /*+ HASH_AGG(), AGG_TO_COP() */ count(distinct a) from (select * from ta union all select * from tb) t;",
        "Plan": [
          "HashAgg 1.00 root  funcs:count(distinct Column#5)->Column#6",
          "└─Union 16000.00 root  ",
          "  ├─HashAgg 8000.00 root  group by:test.ta.a, funcs:firstrow(test.ta.a)->Column#5, funcs:firstrow(test.ta.a)->Column#5",
          "  │ └─TableReader 8000.00 root  data:HashAgg",
          "  │   └─HashAgg 8000.00 cop[tikv]  group by:test.ta.a, ",
          "  │     └─TableFullScan 10000.00 cop[tikv] table:ta keep order:false, stats:pseudo",
          "  └─HashAgg 8000.00 root  group by:test.tb.a, funcs:firstrow(test.tb.a)->Column#5, funcs:firstrow(test.tb.a)->Column#5",
          "    └─TableReader 8000.00 root  data:HashAgg",
          "      └─HashAgg 8000.00 cop[tikv]  group by:test.tb.a, ",
          "        └─TableFullScan 10000.00 cop[tikv] table:tb keep order:false, stats:pseudo"
        ],
        "Result": [
          "1"
        ]
      },
      {
        "SQL": "select distinct DATE_FORMAT(timestamp, '%Y-%m-%d %H') as tt from tc ;",
        "Plan": [
          "HashAgg 16000.00 root  group by:Column#5, funcs:firstrow(Column#6)->Column#3",
          "└─PartitionUnion 16000.00 root  ",
          "  ├─HashAgg 8000.00 root  group by:Column#7, funcs:firstrow(Column#7)->Column#6, funcs:firstrow(Column#7)->Column#5",
          "  │ └─IndexReader 8000.00 root  index:HashAgg",
          "  │   └─HashAgg 8000.00 cop[tikv]  group by:date_format(test.tc.timestamp, \"%Y-%m-%d %H\"), ",
          "  │     └─IndexFullScan 10000.00 cop[tikv] table:tc, partition:p2020072312, index:idx_timestamp(timestamp) keep order:false, stats:pseudo",
          "  └─HashAgg 8000.00 root  group by:Column#10, funcs:firstrow(Column#10)->Column#6, funcs:firstrow(Column#10)->Column#5",
          "    └─IndexReader 8000.00 root  index:HashAgg",
          "      └─HashAgg 8000.00 cop[tikv]  group by:date_format(test.tc.timestamp, \"%Y-%m-%d %H\"), ",
          "        └─IndexFullScan 10000.00 cop[tikv] table:tc, partition:p2020072313, index:idx_timestamp(timestamp) keep order:false, stats:pseudo"
        ],
        "Result": null
      }
    ]
  },
  {
    "Name": "TestPushdownDistinctDisable",
    "Cases": [
      {
        "SQL": "select /*+ HASH_AGG(), AGG_TO_COP() */ avg(distinct a) from t;",
        "Plan": [
          "HashAgg 1.00 root  funcs:avg(distinct Column#6)->Column#5",
          "└─Projection 10000.00 root  cast(test.t.a, decimal(10,0) BINARY)->Column#6",
          "  └─TableReader 10000.00 root  data:TableFullScan",
          "    └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Result": [
          "1.5000"
        ]
      },
      {
        "SQL": "select /*+ HASH_AGG(), AGG_TO_COP() */ a, count(distinct a) from t;",
        "Plan": [
          "Projection 1.00 root  test.t.a, Column#5",
          "└─HashAgg 1.00 root  funcs:count(distinct test.t.a)->Column#5, funcs:firstrow(test.t.a)->test.t.a",
          "  └─TableReader 10000.00 root  data:TableFullScan",
          "    └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 2"
        ]
      },
      {
        "SQL": "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;",
        "Plan": [
          "Projection 8000.00 root  Column#5, test.t.c, Column#5, Column#6, Column#7, Column#8, Column#9",
          "└─HashAgg 8000.00 root  group by:Column#17, funcs:avg(Column#10)->Column#5, funcs:count(distinct Column#11, Column#12)->Column#6, funcs:count(distinct Column#13)->Column#7, funcs:count(distinct Column#14)->Column#8, funcs:sum(Column#15)->Column#9, funcs:firstrow(Column#16)->test.t.c",
          "  └─Projection 10000.00 root  cast(test.t.b, decimal(10,0) BINARY)->Column#10, test.t.a, test.t.b, test.t.a, test.t.c, cast(test.t.b, decimal(10,0) BINARY)->Column#15, test.t.c, test.t.c",
          "    └─TableReader 10000.00 root  data:TableFullScan",
          "      └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Result": [
          "1.0000 1 1.0000 1 1 1 1",
          "1.3333 3 1.3333 3 2 1 4",
          "2.0000 <nil> 2.0000 1 1 0 2"
        ]
      },
      {
        "SQL": "select /*+ STREAM_AGG(), AGG_TO_COP() */ count(distinct c) from t group by c;",
        "Plan": [
          "StreamAgg 8000.00 root  group by:test.t.c, funcs:count(distinct test.t.c)->Column#5",
          "└─IndexReader 10000.00 root  index:IndexFullScan",
          "  └─IndexFullScan 10000.00 cop[tikv] table:t, index:c(c) keep order:true, stats:pseudo"
        ],
        "Result": [
          "0",
          "1",
          "1"
        ]
      },
      {
        "SQL": "select /*+ STREAM_AGG(), AGG_TO_COP() */ count(distinct c) from t;",
        "Plan": [
          "StreamAgg 1.00 root  funcs:count(distinct test.t.c)->Column#5",
          "└─IndexReader 10000.00 root  index:IndexFullScan",
          "  └─IndexFullScan 10000.00 cop[tikv] table:t, index:c(c) keep order:false, stats:pseudo"
        ],
        "Result": [
          "2"
        ]
      },
      {
        "SQL": "select /*+ HASH_AGG(), AGG_TO_COP() */ count(distinct c) from t;",
        "Plan": [
          "HashAgg 1.00 root  funcs:count(distinct test.t.c)->Column#5",
          "└─IndexReader 10000.00 root  index:IndexFullScan",
          "  └─IndexFullScan 10000.00 cop[tikv] table:t, index:c(c) keep order:false, stats:pseudo"
        ],
        "Result": [
          "2"
        ]
      },
      {
        "SQL": "select /*+ AGG_TO_COP() */ count(distinct c) from t group by c;",
        "Plan": [
          "StreamAgg 8000.00 root  group by:test.t.c, funcs:count(distinct test.t.c)->Column#5",
          "└─IndexReader 10000.00 root  index:IndexFullScan",
          "  └─IndexFullScan 10000.00 cop[tikv] table:t, index:c(c) keep order:true, stats:pseudo"
        ],
        "Result": [
          "0",
          "1",
          "1"
        ]
      },
      {
        "SQL": "select /*+ HASH_AGG(), AGG_TO_COP() */ sum(distinct b) from pt;",
        "Plan": [
          "HashAgg 1.00 root  funcs:sum(distinct Column#9)->Column#4",
          "└─Projection 16000.00 root  cast(test.pt.b, decimal(10,0) BINARY)->Column#9",
          "  └─PartitionUnion 16000.00 root  ",
          "    ├─HashAgg 8000.00 root  group by:test.pt.b, funcs:firstrow(test.pt.b)->test.pt.b, funcs:firstrow(test.pt.b)->test.pt.b",
          "    │ └─TableReader 8000.00 root  data:HashAgg",
          "    │   └─HashAgg 8000.00 cop[tikv]  group by:test.pt.b, ",
          "    │     └─TableFullScan 10000.00 cop[tikv] table:pt, partition:p0 keep order:false, stats:pseudo",
          "    └─HashAgg 8000.00 root  group by:test.pt.b, funcs:firstrow(test.pt.b)->test.pt.b, funcs:firstrow(test.pt.b)->test.pt.b",
          "      └─TableReader 8000.00 root  data:HashAgg",
          "        └─HashAgg 8000.00 cop[tikv]  group by:test.pt.b, ",
          "          └─TableFullScan 10000.00 cop[tikv] table:pt, partition:p1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "<nil>"
        ]
      },
      {
        "SQL": "select /*+ HASH_AGG(), AGG_TO_COP() */ count(distinct a) from (select * from ta union all select * from tb) t;",
        "Plan": [
          "HashAgg 1.00 root  funcs:count(distinct Column#5)->Column#6",
          "└─Union 16000.00 root  ",
          "  ├─HashAgg 8000.00 root  group by:test.ta.a, funcs:firstrow(test.ta.a)->Column#5, funcs:firstrow(test.ta.a)->Column#5",
          "  │ └─TableReader 8000.00 root  data:HashAgg",
          "  │   └─HashAgg 8000.00 cop[tikv]  group by:test.ta.a, ",
          "  │     └─TableFullScan 10000.00 cop[tikv] table:ta keep order:false, stats:pseudo",
          "  └─HashAgg 8000.00 root  group by:test.tb.a, funcs:firstrow(test.tb.a)->Column#5, funcs:firstrow(test.tb.a)->Column#5",
          "    └─TableReader 8000.00 root  data:HashAgg",
          "      └─HashAgg 8000.00 cop[tikv]  group by:test.tb.a, ",
          "        └─TableFullScan 10000.00 cop[tikv] table:tb keep order:false, stats:pseudo"
        ],
        "Result": [
          "1"
        ]
      }
    ]
  },
  {
    "Name": "TestPushdownDistinctEnableAggPushDownDisable",
    "Cases": [
      {
        "SQL": "select /*+ HASH_AGG(), AGG_TO_COP() */ sum(distinct b) from pt;",
        "Plan": [
          "HashAgg 1.00 root  funcs:sum(distinct Column#9)->Column#4",
          "└─Projection 16000.00 root  cast(test.pt.b, decimal(10,0) BINARY)->Column#9",
          "  └─PartitionUnion 16000.00 root  ",
          "    ├─HashAgg 8000.00 root  group by:test.pt.b, funcs:firstrow(test.pt.b)->test.pt.b, funcs:firstrow(test.pt.b)->test.pt.b",
          "    │ └─TableReader 8000.00 root  data:HashAgg",
          "    │   └─HashAgg 8000.00 cop[tikv]  group by:test.pt.b, ",
          "    │     └─TableFullScan 10000.00 cop[tikv] table:pt, partition:p0 keep order:false, stats:pseudo",
          "    └─HashAgg 8000.00 root  group by:test.pt.b, funcs:firstrow(test.pt.b)->test.pt.b, funcs:firstrow(test.pt.b)->test.pt.b",
          "      └─TableReader 8000.00 root  data:HashAgg",
          "        └─HashAgg 8000.00 cop[tikv]  group by:test.pt.b, ",
          "          └─TableFullScan 10000.00 cop[tikv] table:pt, partition:p1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "<nil>"
        ]
      },
      {
        "SQL": "select /*+ HASH_AGG(), AGG_TO_COP() */ count(distinct a) from (select * from ta union all select * from tb) t;",
        "Plan": [
          "HashAgg 1.00 root  funcs:count(distinct Column#5)->Column#6",
          "└─Union 20000.00 root  ",
          "  ├─TableReader 10000.00 root  data:TableFullScan",
          "  │ └─TableFullScan 10000.00 cop[tikv] table:ta keep order:false, stats:pseudo",
          "  └─TableReader 10000.00 root  data:TableFullScan",
          "    └─TableFullScan 10000.00 cop[tikv] table:tb keep order:false, stats:pseudo"
        ],
        "Result": [
          "1"
        ]
      },
      {
        "SQL": "select distinct DATE_FORMAT(timestamp, '%Y-%m-%d %H') as tt from tc ;",
        "Plan": [
          "HashAgg 16000.00 root  group by:Column#5, funcs:firstrow(Column#6)->Column#3",
          "└─PartitionUnion 16000.00 root  ",
          "  ├─HashAgg 8000.00 root  group by:Column#7, funcs:firstrow(Column#7)->Column#6, funcs:firstrow(Column#7)->Column#5",
          "  │ └─IndexReader 8000.00 root  index:HashAgg",
          "  │   └─HashAgg 8000.00 cop[tikv]  group by:date_format(test.tc.timestamp, \"%Y-%m-%d %H\"), ",
          "  │     └─IndexFullScan 10000.00 cop[tikv] table:tc, partition:p2020072312, index:idx_timestamp(timestamp) keep order:false, stats:pseudo",
          "  └─HashAgg 8000.00 root  group by:Column#10, funcs:firstrow(Column#10)->Column#6, funcs:firstrow(Column#10)->Column#5",
          "    └─IndexReader 8000.00 root  index:HashAgg",
          "      └─HashAgg 8000.00 cop[tikv]  group by:date_format(test.tc.timestamp, \"%Y-%m-%d %H\"), ",
          "        └─IndexFullScan 10000.00 cop[tikv] table:tc, partition:p2020072313, index:idx_timestamp(timestamp) keep order:false, stats:pseudo"
        ],
        "Result": null
      }
    ]
  },
  {
    "Name": "TestGroupConcatOrderby",
    "Cases": [
      {
        "SQL": "select /*+ agg_to_cop */ group_concat(name ORDER BY name desc SEPARATOR '++'), group_concat(id ORDER BY name desc, id asc SEPARATOR '--') from test;",
        "Plan": [
          "HashAgg 1.00 root  funcs:group_concat(Column#6 order by Column#7 desc separator \"++\")->Column#4, funcs:group_concat(Column#8 order by Column#9 desc, Column#10 separator \"--\")->Column#5",
          "└─Projection 10000.00 root  cast(test.test.name, var_string(20))->Column#6, test.test.name, cast(test.test.id, var_string(20))->Column#8, test.test.name, test.test.id",
          "  └─TableReader 10000.00 root  data:TableFullScan",
          "    └─TableFullScan 10000.00 cop[tikv] table:test keep order:false, stats:pseudo"
        ],
        "Result": [
          "500++200++30++20++20++10 3--3--1--1--2--1"
        ]
      },
      {
        "SQL": "select /*+ agg_to_cop */ group_concat(name ORDER BY name desc SEPARATOR '++'), group_concat(id ORDER BY name desc, id asc SEPARATOR '--') from ptest;",
        "Plan": [
          "HashAgg 1.00 root  funcs:group_concat(Column#6 order by Column#7 desc separator \"++\")->Column#4, funcs:group_concat(Column#8 order by Column#9 desc, Column#10 separator \"--\")->Column#5",
          "└─Projection 10000.00 root  cast(test.ptest.name, var_string(20))->Column#6, test.ptest.name, cast(test.ptest.id, var_string(20))->Column#8, test.ptest.name, test.ptest.id",
          "  └─TableReader 10000.00 root partition:all data:TableFullScan",
          "    └─TableFullScan 10000.00 cop[tikv] table:ptest keep order:false, stats:pseudo"
        ],
        "Result": [
          "500++200++30++20++20++10 3--3--1--1--2--1"
        ]
      },
      {
        "SQL": "select /*+ agg_to_cop */ group_concat(distinct name order by name desc) from test;",
        "Plan": [
          "HashAgg 1.00 root  funcs:group_concat(distinct Column#5 order by Column#6 desc separator \",\")->Column#4",
          "└─Projection 10000.00 root  cast(test.test.name, var_string(20))->Column#5, test.test.name",
          "  └─TableReader 10000.00 root  data:TableFullScan",
          "    └─TableFullScan 10000.00 cop[tikv] table:test keep order:false, stats:pseudo"
        ],
        "Result": [
          "500,200,30,20,10"
        ]
      },
      {
        "SQL": "select /*+ agg_to_cop */ group_concat(distinct name order by name desc) from ptest;",
        "Plan": [
          "HashAgg 1.00 root  funcs:group_concat(distinct Column#5 order by Column#6 desc separator \",\")->Column#4",
          "└─Projection 10000.00 root  cast(test.ptest.name, var_string(20))->Column#5, test.ptest.name",
          "  └─TableReader 10000.00 root partition:all data:TableFullScan",
          "    └─TableFullScan 10000.00 cop[tikv] table:ptest keep order:false, stats:pseudo"
        ],
        "Result": [
          "500,200,30,20,10"
        ]
      }
    ]
  },
  {
    "Name": "TestDAGPlanBuilderWindow",
    "Cases": [
      {
        "SQL": "select lead(a, 1) over (partition by null) as c from t",
        "Best": "IndexReader(Index(t.f)[[NULL,+inf]])->Window(lead(test.t.a, 1)->Column#14 over())->Projection"
      }
    ]
  },
  {
    "Name": "TestDAGPlanBuilderWindowParallel",
    "Cases": [
      {
        "SQL": "select lead(a, 1) over (partition by null) as c from t",
        "Best": "IndexReader(Index(t.f)[[NULL,+inf]])->Window(lead(test.t.a, 1)->Column#14 over())->Projection"
      },
      {
        "SQL": "select lead(a, 1) over (partition by b) as c from t",
        "Best": "TableReader(Table(t))->Sort->Window(lead(test.t.a, 1)->Column#14 over(partition by test.t.b))->Partition(execution info: concurrency:4, data sources:[TableReader_10])->Projection"
      }
    ]
  },
  {
    "Name": "TestNominalSort",
    "Cases": [
      {
        "SQL": "select /*+ TIDB_SMJ(t1, t2) */ t1.a from t t1, t t2 where t1.a = t2.b order by t1.a",
        "Plan": [
          "MergeJoin 12487.50 root  inner join, left key:test.t.a, right key:test.t.b",
          "├─IndexReader(Build) 9990.00 root  index:IndexFullScan",
          "│ └─IndexFullScan 9990.00 cop[tikv] table:t2, index:idx_b(b) keep order:true, stats:pseudo",
          "└─IndexReader(Probe) 9990.00 root  index:IndexFullScan",
          "  └─IndexFullScan 9990.00 cop[tikv] table:t1, index:idx_a(a) keep order:true, stats:pseudo"
        ],
        "Result": [
          "1",
          "1",
          "2"
        ]
      },
      {
        "SQL": "select /*+ TIDB_SMJ(t1, t2) */ t1.a from t t1, t t2 where t1.a = t2.b order by t1.a+1",
        "Plan": [
          "Projection 12487.50 root  test.t.a",
          "└─Projection 12487.50 root  test.t.a, plus(test.t.a, 1)->Column#7",
          "  └─MergeJoin 12487.50 root  inner join, left key:test.t.a, right key:test.t.b",
          "    ├─IndexReader(Build) 9990.00 root  index:IndexFullScan",
          "    │ └─IndexFullScan 9990.00 cop[tikv] table:t2, index:idx_b(b) keep order:true, stats:pseudo",
          "    └─IndexReader(Probe) 9990.00 root  index:IndexFullScan",
          "      └─IndexFullScan 9990.00 cop[tikv] table:t1, index:idx_a(a) keep order:true, stats:pseudo"
        ],
        "Result": [
          "1",
          "1",
          "2"
        ]
      },
      {
        "SQL": "select /*+ TIDB_SMJ(t1, t2) */ t1.a from t t1, t t2 where t1.a = t2.b order by t1.a-1",
        "Plan": [
          "Projection 12487.50 root  test.t.a",
          "└─Projection 12487.50 root  test.t.a, minus(test.t.a, 1)->Column#7",
          "  └─MergeJoin 12487.50 root  inner join, left key:test.t.a, right key:test.t.b",
          "    ├─IndexReader(Build) 9990.00 root  index:IndexFullScan",
          "    │ └─IndexFullScan 9990.00 cop[tikv] table:t2, index:idx_b(b) keep order:true, stats:pseudo",
          "    └─IndexReader(Probe) 9990.00 root  index:IndexFullScan",
          "      └─IndexFullScan 9990.00 cop[tikv] table:t1, index:idx_a(a) keep order:true, stats:pseudo"
        ],
        "Result": [
          "1",
          "1",
          "2"
        ]
      },
      {
        "SQL": "select /*+ TIDB_SMJ(t1, t2) */ t1.a from t t1, t t2 where t1.a = t2.b order by -t1.a",
        "Plan": [
          "Projection 12487.50 root  test.t.a",
          "└─Projection 12487.50 root  test.t.a, unaryminus(test.t.a)->Column#7",
          "  └─MergeJoin 12487.50 root  inner join, left key:test.t.a, right key:test.t.b",
          "    ├─IndexReader(Build) 9990.00 root  index:IndexFullScan",
          "    │ └─IndexFullScan 9990.00 cop[tikv] table:t2, index:idx_b(b) keep order:true, desc, stats:pseudo",
          "    └─IndexReader(Probe) 9990.00 root  index:IndexFullScan",
          "      └─IndexFullScan 9990.00 cop[tikv] table:t1, index:idx_a(a) keep order:true, desc, stats:pseudo"
        ],
        "Result": [
          "2",
          "1",
          "1"
        ]
      },
      {
        "SQL": "select /*+ TIDB_SMJ(t1, t2) */ t1.a from t t1, t t2 where t1.a = t2.b order by -t1.a+3",
        "Plan": [
          "Projection 12487.50 root  test.t.a",
          "└─Projection 12487.50 root  test.t.a, plus(unaryminus(test.t.a), 3)->Column#7",
          "  └─MergeJoin 12487.50 root  inner join, left key:test.t.a, right key:test.t.b",
          "    ├─IndexReader(Build) 9990.00 root  index:IndexFullScan",
          "    │ └─IndexFullScan 9990.00 cop[tikv] table:t2, index:idx_b(b) keep order:true, desc, stats:pseudo",
          "    └─IndexReader(Probe) 9990.00 root  index:IndexFullScan",
          "      └─IndexFullScan 9990.00 cop[tikv] table:t1, index:idx_a(a) keep order:true, desc, stats:pseudo"
        ],
        "Result": [
          "2",
          "1",
          "1"
        ]
      },
      {
        "SQL": "select /*+ TIDB_SMJ(t1, t2) */ t1.a from t t1, t t2 where t1.a = t2.b order by 1+t1.a",
        "Plan": [
          "Projection 12487.50 root  test.t.a",
          "└─Projection 12487.50 root  test.t.a, plus(1, test.t.a)->Column#7",
          "  └─MergeJoin 12487.50 root  inner join, left key:test.t.a, right key:test.t.b",
          "    ├─IndexReader(Build) 9990.00 root  index:IndexFullScan",
          "    │ └─IndexFullScan 9990.00 cop[tikv] table:t2, index:idx_b(b) keep order:true, stats:pseudo",
          "    └─IndexReader(Probe) 9990.00 root  index:IndexFullScan",
          "      └─IndexFullScan 9990.00 cop[tikv] table:t1, index:idx_a(a) keep order:true, stats:pseudo"
        ],
        "Result": [
          "1",
          "1",
          "2"
        ]
      },
      {
        "SQL": "select /*+ TIDB_SMJ(t1, t2) */ t1.a from t t1, t t2 where t1.a = t2.b order by 1-t1.a",
        "Plan": [
          "Projection 12487.50 root  test.t.a",
          "└─Projection 12487.50 root  test.t.a, minus(1, test.t.a)->Column#7",
          "  └─MergeJoin 12487.50 root  inner join, left key:test.t.a, right key:test.t.b",
          "    ├─IndexReader(Build) 9990.00 root  index:IndexFullScan",
          "    │ └─IndexFullScan 9990.00 cop[tikv] table:t2, index:idx_b(b) keep order:true, desc, stats:pseudo",
          "    └─IndexReader(Probe) 9990.00 root  index:IndexFullScan",
          "      └─IndexFullScan 9990.00 cop[tikv] table:t1, index:idx_a(a) keep order:true, desc, stats:pseudo"
        ],
        "Result": [
          "2",
          "1",
          "1"
        ]
      },
      {
        "SQL": "select /*+ TIDB_SMJ(t1, t2) */ t1.a from t t1, t t2 where t1.a = t2.b order by 1-t1.a+3",
        "Plan": [
          "Projection 12487.50 root  test.t.a",
          "└─Projection 12487.50 root  test.t.a, plus(minus(1, test.t.a), 3)->Column#7",
          "  └─MergeJoin 12487.50 root  inner join, left key:test.t.a, right key:test.t.b",
          "    ├─IndexReader(Build) 9990.00 root  index:IndexFullScan",
          "    │ └─IndexFullScan 9990.00 cop[tikv] table:t2, index:idx_b(b) keep order:true, desc, stats:pseudo",
          "    └─IndexReader(Probe) 9990.00 root  index:IndexFullScan",
          "      └─IndexFullScan 9990.00 cop[tikv] table:t1, index:idx_a(a) keep order:true, desc, stats:pseudo"
        ],
        "Result": [
          "2",
          "1",
          "1"
        ]
      },
      {
        "SQL": "select /*+ TIDB_SMJ(t1, t2) */ t1.a from t t1, t t2 where t1.a = t2.b order by 1+t1.a+3",
        "Plan": [
          "Projection 12487.50 root  test.t.a",
          "└─Projection 12487.50 root  test.t.a, plus(plus(1, test.t.a), 3)->Column#7",
          "  └─MergeJoin 12487.50 root  inner join, left key:test.t.a, right key:test.t.b",
          "    ├─IndexReader(Build) 9990.00 root  index:IndexFullScan",
          "    │ └─IndexFullScan 9990.00 cop[tikv] table:t2, index:idx_b(b) keep order:true, stats:pseudo",
          "    └─IndexReader(Probe) 9990.00 root  index:IndexFullScan",
          "      └─IndexFullScan 9990.00 cop[tikv] table:t1, index:idx_a(a) keep order:true, stats:pseudo"
        ],
        "Result": [
          "1",
          "1",
          "2"
        ]
      },
      {
        "SQL": "select /*+ TIDB_SMJ(t1, t2) */ t1.a from t t1, t t2 where t1.a = t2.b order by 3*t1.a",
        "Plan": [
          "Projection 12487.50 root  test.t.a",
          "└─Sort 12487.50 root  Column#7",
          "  └─Projection 12487.50 root  test.t.a, mul(3, test.t.a)->Column#7",
          "    └─MergeJoin 12487.50 root  inner join, left key:test.t.a, right key:test.t.b",
          "      ├─IndexReader(Build) 9990.00 root  index:IndexFullScan",
          "      │ └─IndexFullScan 9990.00 cop[tikv] table:t2, index:idx_b(b) keep order:true, stats:pseudo",
          "      └─IndexReader(Probe) 9990.00 root  index:IndexFullScan",
          "        └─IndexFullScan 9990.00 cop[tikv] table:t1, index:idx_a(a) keep order:true, stats:pseudo"
        ],
        "Result": [
          "1",
          "1",
          "2"
        ]
      }
    ]
  },
  {
    "Name": "TestInlineProjection",
    "Cases": [
      {
        "SQL": "select /*+ HASH_JOIN(t1) */ t1.b, t2.b from t1, t2 where t1.a = t2.a;",
        "Plan": "LeftHashJoin{TableReader(Table(t1)->Sel([not(isnull(test.t1.a))]))->TableReader(Table(t2)->Sel([not(isnull(test.t2.a))]))}(test.t1.a,test.t2.a)",
        "Hints": "use_index(@`sel_1` `test`.`t1` ), use_index(@`sel_1` `test`.`t2` ), hash_join(@`sel_1` `test`.`t1`)"
      },
      {
        "SQL": "select /*+ HASH_JOIN(t1) */ t1.b, t2.b from t1 inner join t2 on t1.a = t2.a;",
        "Plan": "LeftHashJoin{TableReader(Table(t1)->Sel([not(isnull(test.t1.a))]))->TableReader(Table(t2)->Sel([not(isnull(test.t2.a))]))}(test.t1.a,test.t2.a)",
        "Hints": "use_index(@`sel_1` `test`.`t1` ), use_index(@`sel_1` `test`.`t2` ), hash_join(@`sel_1` `test`.`t1`)"
      },
      {
        "SQL": "select /*+ HASH_JOIN(t1) */ t1.b, t2.b from t1 left outer join t2 on t1.a = t2.a;",
        "Plan": "LeftHashJoin{TableReader(Table(t1))->TableReader(Table(t2)->Sel([not(isnull(test.t2.a))]))}(test.t1.a,test.t2.a)",
        "Hints": "use_index(@`sel_1` `test`.`t1` ), use_index(@`sel_1` `test`.`t2` ), hash_join(@`sel_1` `test`.`t1`)"
      },
      {
        "SQL": "select /*+ HASH_JOIN(t1) */ t1.b, t2.b from t1 right outer join t2 on t1.a = t2.a;",
        "Plan": "RightHashJoin{TableReader(Table(t1)->Sel([not(isnull(test.t1.a))]))->TableReader(Table(t2))}(test.t1.a,test.t2.a)",
        "Hints": "use_index(@`sel_1` `test`.`t1` ), use_index(@`sel_1` `test`.`t2` ), hash_join(@`sel_1` `test`.`t1`)"
      },
      {
        "SQL": "select 1 from (select /*+ HASH_JOIN(t1) */ t1.a in (select t2.a from t2) from t1) x;",
        "Plan": "LeftHashJoin{IndexReader(Index(t1.idx_a)[[NULL,+inf]])->IndexReader(Index(t2.idx_a)[[NULL,+inf]])}->Projection",
        "Hints": "use_index(@`sel_2` `test`.`t1` `idx_a`), use_index(@`sel_3` `test`.`t2` `idx_a`), hash_join(@`sel_2` `test`.`t1`)"
      },
      {
        "SQL": "select 1 from (select /*+ HASH_JOIN(t1) */ t1.a not in (select t2.a from t2) from t1) x;",
        "Plan": "LeftHashJoin{IndexReader(Index(t1.idx_a)[[NULL,+inf]])->IndexReader(Index(t2.idx_a)[[NULL,+inf]])}->Projection",
        "Hints": "use_index(@`sel_2` `test`.`t1` `idx_a`), use_index(@`sel_3` `test`.`t2` `idx_a`), hash_join(@`sel_2` `test`.`t1`)"
      },
      {
        "SQL": "select /*+ INL_JOIN(t1) */ t1.b, t2.b from t1 inner join t2 on t1.a = t2.a;",
        "Plan": "IndexJoin{IndexLookUp(Index(t1.idx_a)[[NULL,NULL]]->Sel([not(isnull(test.t1.a))]), Table(t1))->TableReader(Table(t2)->Sel([not(isnull(test.t2.a))]))}(test.t2.a,test.t1.a)",
        "Hints": "use_index(@`sel_1` `test`.`t1` `idx_a`), use_index(@`sel_1` `test`.`t2` ), inl_join(@`sel_1` `test`.`t1`)"
      },
      {
        "SQL": "select /*+ INL_HASH_JOIN(t1) */ t1.b, t2.b from t1 inner join t2 on t1.a = t2.a;",
        "Plan": "IndexHashJoin{IndexLookUp(Index(t1.idx_a)[[NULL,NULL]]->Sel([not(isnull(test.t1.a))]), Table(t1))->TableReader(Table(t2)->Sel([not(isnull(test.t2.a))]))}(test.t2.a,test.t1.a)",
        "Hints": "use_index(@`sel_1` `test`.`t1` `idx_a`), use_index(@`sel_1` `test`.`t2` ), inl_hash_join(@`sel_1` `test`.`t1`)"
      },
      {
        "SQL": "select /*+ INL_MERGE_JOIN(t1) */ t1.b, t2.b from t1 inner join t2 on t1.a = t2.a;",
        "Plan": "IndexMergeJoin{IndexLookUp(Index(t1.idx_a)[[NULL,NULL]]->Sel([not(isnull(test.t1.a))]), Table(t1))->Projection->TableReader(Table(t2)->Sel([not(isnull(test.t2.a))]))}(test.t2.a,test.t1.a)",
        "Hints": "use_index(@`sel_1` `test`.`t1` `idx_a`), use_index(@`sel_1` `test`.`t2` ), inl_merge_join(@`sel_1` `test`.`t1`)"
      },
      {
        "SQL": "select /*+ MERGE_JOIN(t1) */ t1.b, t2.b from t1 inner join t2 on t1.a = t2.a;",
        "Plan": "MergeInnerJoin{IndexLookUp(Index(t1.idx_a)[[-inf,+inf]], Table(t1))->Projection->IndexLookUp(Index(t2.idx_a)[[-inf,+inf]], Table(t2))->Projection}(test.t1.a,test.t2.a)",
        "Hints": "use_index(@`sel_1` `test`.`t1` `idx_a`), use_index(@`sel_1` `test`.`t2` `idx_a`), merge_join(@`sel_1` `test`.`t1`)"
      }
    ]
  },
  {
    "Name": "TestHintFromDiffDatabase",
    "Cases": [
      {
        "SQL": "select /*+ inl_hash_join(test.t1) */ * from test.t2 join test.t1 on test.t2.a = test.t1.a",
        "Plan": "IndexHashJoin{IndexReader(Index(t2.idx_a)[[-inf,+inf]])->IndexReader(Index(t1.idx_a)[[NULL,NULL]]->Sel([not(isnull(test.t1.a))]))}(test.t2.a,test.t1.a)"
      }
    ]
  },
  {
    "Name": "TestNthPlanHintWithExplain",
    "Cases": [
      {
        "SQL": "select /*+nth_plan(1)*/ * from test.tt where a=1 and b=1",
        "Plan": [
          "TableReader 0.01 root  data:Selection",
          "└─Selection 0.01 cop[tikv]  eq(test.tt.a, 1), eq(test.tt.b, 1)",
          "  └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select /*+nth_plan(2)*/ * from test.tt where a=1 and b=1;",
        "Plan": [
          "IndexLookUp 0.01 root  ",
          "├─IndexRangeScan(Build) 10.00 cop[tikv] table:tt, index:a(a) range:[1,1], keep order:false, stats:pseudo",
          "└─Selection(Probe) 0.01 cop[tikv]  eq(test.tt.b, 1)",
          "  └─TableRowIDScan 10.00 cop[tikv] table:tt keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select /*+nth_plan(3)*/ * from test.tt where a=1 and b=1;",
        "Plan": [
          "IndexLookUp 0.01 root  ",
          "├─IndexRangeScan(Build) 10.00 cop[tikv] table:tt, index:b(b) range:[1,1], keep order:false, stats:pseudo",
          "└─Selection(Probe) 0.01 cop[tikv]  eq(test.tt.a, 1)",
          "  └─TableRowIDScan 10.00 cop[tikv] table:tt keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select /*+nth_plan(2)*/ * from test.tt where a=1 and b=1;",
        "Plan": [
          "IndexLookUp 0.01 root  ",
          "├─IndexRangeScan(Build) 10.00 cop[tikv] table:tt, index:a(a) range:[1,1], keep order:false, stats:pseudo",
          "└─Selection(Probe) 0.01 cop[tikv]  eq(test.tt.b, 1)",
          "  └─TableRowIDScan 10.00 cop[tikv] table:tt keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select * from test.tt where a=1 and b=1",
        "Plan": [
          "IndexLookUp 0.01 root  ",
          "├─IndexRangeScan(Build) 10.00 cop[tikv] table:tt, index:a(a) range:[1,1], keep order:false, stats:pseudo",
          "└─Selection(Probe) 0.01 cop[tikv]  eq(test.tt.b, 1)",
          "  └─TableRowIDScan 10.00 cop[tikv] table:tt keep order:false, stats:pseudo"
        ]
      }
    ]
  },
  {
    "Name": "TestINMJHint",
    "Cases": [
      {
        "SQL": "select /*+ inl_merge_join(t2) */ t1.a, t2.a from t1 left join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "IndexMergeJoin 12500.00 root  left outer join, inner:TableReader, outer key:test.t1.a, inner key:test.t2.a, other cond:eq(test.t1.b, test.t2.b)",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableRangeScan",
          "  └─TableRangeScan 10000.00 cop[tikv] table:t2 range: decided by [test.t1.a], keep order:true, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 <nil>"
        ]
      },
      {
        "SQL": "select /*+ inl_hash_join(t2) */ t1.a, t2.a from t1 left join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "IndexHashJoin 12500.00 root  left outer join, inner:TableReader, outer key:test.t1.a, inner key:test.t2.a, equal cond:eq(test.t1.a, test.t2.a), eq(test.t1.b, test.t2.b)",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableRangeScan",
          "  └─TableRangeScan 10000.00 cop[tikv] table:t2 range: decided by [test.t1.a], keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 <nil>"
        ]
      },
      {
        "SQL": "select /*+ inl_join(t2) */ t1.a, t2.a from t1 left join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "IndexJoin 12500.00 root  left outer join, inner:TableReader, outer key:test.t1.a, inner key:test.t2.a, equal cond:eq(test.t1.a, test.t2.a), eq(test.t1.b, test.t2.b)",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableRangeScan",
          "  └─TableRangeScan 10000.00 cop[tikv] table:t2 range: decided by [test.t1.a], keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 <nil>"
        ]
      },
      {
        "SQL": "select /*+ hash_join(t2) */ t1.a, t2.a from t1 left join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  left outer join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 <nil>"
        ]
      }
    ]
  },
  {
    "Name": "TestEliminateMaxOneRow",
    "Cases": [
      {
        "SQL": "select a from t2 where t2.a < (select t1.a from t1 where t1.a = t2.a);",
        "Plan": [
          "HashJoin 9990.00 root  inner join, equal:[eq(test.t2.a, test.t1.a)], other cond:lt(test.t2.a, test.t1.a)",
          "├─IndexReader(Build) 7992.00 root  index:Selection",
          "│ └─Selection 7992.00 cop[tikv]  lt(test.t1.a, test.t1.a)",
          "│   └─IndexFullScan 9990.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo",
          "└─TableReader(Probe) 7992.00 root  data:Selection",
          "  └─Selection 7992.00 cop[tikv]  lt(test.t2.a, test.t2.a), not(isnull(test.t2.a))",
          "    └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ],
        "Result": null
      },
      {
        "SQL": "select a from t2 where t2.a < (select t1.a from t1 where t1.b = t2.b and t1.a is null);",
        "Plan": [
          "Projection 9990.00 root  test.t2.a",
          "└─Apply 9990.00 root  CARTESIAN inner join, other cond:lt(test.t2.a, test.t1.a)",
          "  ├─TableReader(Build) 9990.00 root  data:Selection",
          "  │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t2.a))",
          "  │   └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "  └─Selection(Probe) 7992.00 root  not(isnull(test.t1.a))",
          "    └─MaxOneRow 9990.00 root  ",
          "      └─IndexLookUp 9.99 root  ",
          "        ├─IndexRangeScan(Build) 9990.00 cop[tikv] table:t1, index:idx_a(a) range:[NULL,NULL], keep order:false, stats:pseudo",
          "        └─Selection(Probe) 9.99 cop[tikv]  eq(test.t1.b, test.t2.b)",
          "          └─TableRowIDScan 9990.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": null
      },
      {
        "SQL": "select a from t2 where t2.a < (select t3.a from t3 where t3.a = t2.a);",
        "Plan": [
          "Projection 9990.00 root  test.t2.a",
          "└─Apply 9990.00 root  CARTESIAN inner join, other cond:lt(test.t2.a, test.t3.a)",
          "  ├─TableReader(Build) 9990.00 root  data:Selection",
          "  │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t2.a))",
          "  │   └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "  └─Selection(Probe) 7992.00 root  not(isnull(test.t3.a))",
          "    └─MaxOneRow 9990.00 root  ",
          "      └─IndexReader 19980.00 root  index:IndexRangeScan",
          "        └─IndexRangeScan 19980.00 cop[tikv] table:t3, index:idx_abc(a, b, c) range: decided by [eq(test.t3.a, test.t2.a)], keep order:false, stats:pseudo"
        ],
        "Result": null
      }
    ]
  },
  {
    "Name": "TestEnumIndex",
    "Cases": [
      {
        "SQL": "select e from t where e = 'b'",
        "Plan": [
          "IndexReader 10.00 root  index:IndexRangeScan",
          "└─IndexRangeScan 10.00 cop[tikv] table:t, index:idx(e) range:[\"b\",\"b\"], keep order:false, stats:pseudo"
        ],
        "Result": [
          "b"
        ]
      },
      {
        "SQL": "select e from t where e != 'b'",
        "Plan": [
          "IndexReader 40.00 root  index:IndexRangeScan",
          "└─IndexRangeScan 40.00 cop[tikv] table:t, index:idx(e) range:[\"\",\"\"], [\"c\",\"c\"], [\"a\",\"a\"], [\"\",\"\"], keep order:false, stats:pseudo"
        ],
        "Result": [
          "",
          "",
          "a",
          "c"
        ]
      },
      {
        "SQL": "select e from t where e > 'b'",
        "Plan": [
          "IndexReader 10.00 root  index:IndexRangeScan",
          "└─IndexRangeScan 10.00 cop[tikv] table:t, index:idx(e) range:[\"c\",\"c\"], keep order:false, stats:pseudo"
        ],
        "Result": [
          "c"
        ]
      },
      {
        "SQL": "select e from t where e >= 'b'",
        "Plan": [
          "IndexReader 20.00 root  index:IndexRangeScan",
          "└─IndexRangeScan 20.00 cop[tikv] table:t, index:idx(e) range:[\"c\",\"c\"], [\"b\",\"b\"], keep order:false, stats:pseudo"
        ],
        "Result": [
          "b",
          "c"
        ]
      },
      {
        "SQL": "select e from t where e < 'b'",
        "Plan": [
          "IndexReader 30.00 root  index:IndexRangeScan",
          "└─IndexRangeScan 30.00 cop[tikv] table:t, index:idx(e) range:[\"\",\"\"], [\"a\",\"a\"], [\"\",\"\"], keep order:false, stats:pseudo"
        ],
        "Result": [
          "",
          "",
          "a"
        ]
      },
      {
        "SQL": "select e from t where e <= 'b'",
        "Plan": [
          "IndexReader 40.00 root  index:IndexRangeScan",
          "└─IndexRangeScan 40.00 cop[tikv] table:t, index:idx(e) range:[\"\",\"\"], [\"b\",\"b\"], [\"a\",\"a\"], [\"\",\"\"], keep order:false, stats:pseudo"
        ],
        "Result": [
          "",
          "",
          "a",
          "b"
        ]
      },
      {
        "SQL": "select e from t where e = 2",
        "Plan": [
          "IndexReader 10.00 root  index:IndexRangeScan",
          "└─IndexRangeScan 10.00 cop[tikv] table:t, index:idx(e) range:[\"b\",\"b\"], keep order:false, stats:pseudo"
        ],
        "Result": [
          "b"
        ]
      },
      {
        "SQL": "select e from t where e != 2",
        "Plan": [
          "IndexReader 6656.67 root  index:IndexRangeScan",
          "└─IndexRangeScan 6656.67 cop[tikv] table:t, index:idx(e) range:[-inf,\"b\"), (\"b\",+inf], keep order:false, stats:pseudo"
        ],
        "Result": [
          "",
          "",
          "a",
          "c"
        ]
      },
      {
        "SQL": "select e from t where e > 2",
        "Plan": [
          "IndexReader 3333.33 root  index:IndexRangeScan",
          "└─IndexRangeScan 3333.33 cop[tikv] table:t, index:idx(e) range:(\"b\",+inf], keep order:false, stats:pseudo"
        ],
        "Result": [
          "",
          "a"
        ]
      },
      {
        "SQL": "select e from t where e >= 2",
        "Plan": [
          "IndexReader 3333.33 root  index:IndexRangeScan",
          "└─IndexRangeScan 3333.33 cop[tikv] table:t, index:idx(e) range:[\"b\",+inf], keep order:false, stats:pseudo"
        ],
        "Result": [
          "",
          "a",
          "b"
        ]
      },
      {
        "SQL": "select e from t where e < 2",
        "Plan": [
          "IndexReader 3323.33 root  index:IndexRangeScan",
          "└─IndexRangeScan 3323.33 cop[tikv] table:t, index:idx(e) range:[-inf,\"b\"), keep order:false, stats:pseudo"
        ],
        "Result": [
          "",
          "c"
        ]
      },
      {
        "SQL": "select e from t where e <= 2",
        "Plan": [
          "IndexReader 3323.33 root  index:IndexRangeScan",
          "└─IndexRangeScan 3323.33 cop[tikv] table:t, index:idx(e) range:[-inf,\"b\"], keep order:false, stats:pseudo"
        ],
        "Result": [
          "",
          "b",
          "c"
        ]
      },
      {
        "SQL": "select e from t where e > ''",
        "Plan": [
          "IndexReader 30.00 root  index:IndexRangeScan",
          "└─IndexRangeScan 30.00 cop[tikv] table:t, index:idx(e) range:[\"c\",\"c\"], [\"b\",\"b\"], [\"a\",\"a\"], keep order:false, stats:pseudo"
        ],
        "Result": [
          "a",
          "b",
          "c"
        ]
      },
      {
        "SQL": "select e from t where e > 'd'",
        "Plan": [
          "TableDual 0.00 root  rows:0"
        ],
        "Result": null
      },
      {
        "SQL": "select e from t where e > -1",
        "Plan": [
          "IndexReader 3333.33 root  index:IndexRangeScan",
          "└─IndexRangeScan 3333.33 cop[tikv] table:t, index:idx(e) range:[\"\",+inf], keep order:false, stats:pseudo"
        ],
        "Result": [
          "",
          "",
          "a",
          "b",
          "c"
        ]
      },
      {
        "SQL": "select e from t where e > 5",
        "Plan": [
          "IndexReader 3333.33 root  index:IndexRangeScan",
          "└─IndexRangeScan 3333.33 cop[tikv] table:t, index:idx(e) range:(\"\",+inf], keep order:false, stats:pseudo"
        ],
        "Result": null
      },
      {
        "SQL": "select e from t where e = ''",
        "Plan": [
          "IndexReader 20.00 root  index:IndexRangeScan",
          "└─IndexRangeScan 20.00 cop[tikv] table:t, index:idx(e) range:[\"\",\"\"], [\"\",\"\"], keep order:false, stats:pseudo"
        ],
        "Result": [
          "",
          ""
        ]
      },
      {
        "SQL": "select e from t where e != ''",
        "Plan": [
          "IndexReader 30.00 root  index:IndexRangeScan",
          "└─IndexRangeScan 30.00 cop[tikv] table:t, index:idx(e) range:[\"c\",\"c\"], [\"b\",\"b\"], [\"a\",\"a\"], keep order:false, stats:pseudo"
        ],
        "Result": [
          "a",
          "b",
          "c"
        ]
      }
    ]
  },
  {
    "Name": "TestIssue27233",
    "Cases": [
      {
        "SQL": "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;",
        "Plan": [
          "Sort 0.80 root  test.pk_s_multi_31.col2",
          "└─Projection 0.80 root  test.pk_s_multi_31.col2",
          "  └─Selection 0.80 root  gt(Column#7, 2)",
          "    └─HashAgg 1.00 root  group by:test.pk_s_multi_31.col1, test.pk_s_multi_31.col2, funcs:firstrow(test.pk_s_multi_31.col2)->test.pk_s_multi_31.col2, funcs:count(distinct test.pk_s_multi_31.col1, test.pk_s_multi_31.col2)->Column#7",
          "      └─HashJoin 100000000.00 root  CARTESIAN left outer join, other cond:gt(test.pk_s_multi_31.col1, test.pk_s_multi_31.col1)",
          "        ├─IndexReader(Build) 10000.00 root  index:IndexFullScan",
          "        │ └─IndexFullScan 10000.00 cop[tikv] table:T2, index:PRIMARY(COL1, COL2) keep order:false, stats:pseudo",
          "        └─IndexReader(Probe) 10000.00 root  index:IndexFullScan",
          "          └─IndexFullScan 10000.00 cop[tikv] table:T1, index:PRIMARY(COL1, COL2) keep order:false, stats:pseudo"
        ],
        "Result": [
          "100"
        ]
      }
    ]
  },
  {
    "Name": "TestSelectionPartialPushDown",
    "Cases": [
      {
        "SQL": "select * from t1 where a > 1 and b > 1",
        "Plan": [
          "Selection 1111.11 root  gt(test.t1.b, 1)",
          "└─TableReader 3333.33 root  data:Selection",
          "  └─Selection 3333.33 cop[tikv]  gt(test.t1.a, 1)",
          "    └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select * from t2 use index(idx_a) where a > 1 and b > 1 and c > 1",
        "Plan": [
          "Selection 370.37 root  gt(test.t2.b, 1)",
          "└─IndexLookUp 1111.11 root  ",
          "  ├─IndexRangeScan(Build) 3333.33 cop[tikv] table:t2, index:idx_a(a) range:(1,+inf], keep order:false, stats:pseudo",
          "  └─Selection(Probe) 1111.11 cop[tikv]  gt(test.t2.c, 1)",
          "    └─TableRowIDScan 3333.33 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ]
      }
    ]
  },
  {
    "Name": "TestIssue28316",
    "Cases": [
      {
        "SQL": "select * from t where t.a < 3 and t.a < 3",
        "Plan": [
          "TableReader 3323.33 root  data:Selection",
          "└─Selection 3323.33 cop[tikv]  lt(test.t.a, 3)",
          "  └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ]
      }
    ]
  },
  {
    "Name": "TestSkewDistinctAgg",
    "Cases": [
      {
        "SQL": "select date_format(d,'%Y') as df, sum(a), count(b), count(distinct c) from t group by date_format(d,'%Y')",
        "Plan": [
          "Projection 8000.00 root  date_format(test.t.d, %Y)->Column#9, Column#6, cast(Column#13, bigint(21) BINARY)->Column#7, Column#8",
          "└─HashAgg 8000.00 root  group by:Column#23, funcs:sum(Column#19)->Column#6, funcs:sum(Column#20)->Column#13, funcs:count(Column#21)->Column#8, funcs:firstrow(Column#22)->test.t.d",
          "  └─Projection 8000.00 root  Column#11, cast(Column#12, decimal(20,0) BINARY)->Column#20, test.t.c, test.t.d, date_format(test.t.d, %Y)->Column#23",
          "    └─HashAgg 8000.00 root  group by:Column#14, test.t.c, funcs:sum(Column#15)->Column#11, funcs:count(Column#16)->Column#12, funcs:firstrow(test.t.c)->test.t.c, funcs:firstrow(Column#18)->test.t.d",
          "      └─TableReader 8000.00 root  data:HashAgg",
          "        └─HashAgg 8000.00 cop[tikv]  group by:date_format(test.t.d, \"%Y\"), test.t.c, funcs:sum(test.t.a)->Column#15, funcs:count(test.t.b)->Column#16, funcs:firstrow(test.t.d)->Column#18",
          "          └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select d, a, count(*), count(b), count(distinct c) from t group by d, a",
        "Plan": [
          "Projection 8000.00 root  test.t.d, test.t.a, cast(Column#10, bigint(21) BINARY)->Column#6, cast(Column#12, bigint(21) BINARY)->Column#7, Column#8",
          "└─HashAgg 8000.00 root  group by:Column#23, Column#24, funcs:sum(Column#18)->Column#10, funcs:sum(Column#19)->Column#12, funcs:count(Column#20)->Column#8, funcs:firstrow(Column#21)->test.t.a, funcs:firstrow(Column#22)->test.t.d",
          "  └─Projection 8000.00 root  cast(Column#9, decimal(20,0) BINARY)->Column#18, cast(Column#11, decimal(20,0) BINARY)->Column#19, test.t.c, test.t.a, test.t.d, test.t.d, test.t.a",
          "    └─HashAgg 8000.00 root  group by:test.t.a, test.t.c, test.t.d, funcs:count(Column#13)->Column#9, funcs:count(Column#14)->Column#11, funcs:firstrow(test.t.c)->test.t.c, funcs:firstrow(test.t.a)->test.t.a, funcs:firstrow(test.t.d)->test.t.d",
          "      └─TableReader 8000.00 root  data:HashAgg",
          "        └─HashAgg 8000.00 cop[tikv]  group by:test.t.a, test.t.c, test.t.d, funcs:count(1)->Column#13, funcs:count(test.t.b)->Column#14",
          "          └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select d, sum(a), count(b), avg(distinct c) from t group by d",
        "Plan": [
          "Projection 8000.00 root  test.t.d, Column#6, cast(Column#11, bigint(21) BINARY)->Column#7, Column#8",
          "└─HashAgg 8000.00 root  group by:Column#20, funcs:sum(Column#16)->Column#6, funcs:sum(Column#17)->Column#11, funcs:avg(Column#18)->Column#8, funcs:firstrow(Column#19)->test.t.d",
          "  └─Projection 8000.00 root  Column#9, cast(Column#10, decimal(20,0) BINARY)->Column#17, cast(test.t.c, decimal(10,0) BINARY)->Column#18, test.t.d, test.t.d",
          "    └─HashAgg 8000.00 root  group by:test.t.c, test.t.d, funcs:sum(Column#12)->Column#9, funcs:count(Column#13)->Column#10, funcs:firstrow(test.t.c)->test.t.c, funcs:firstrow(test.t.d)->test.t.d",
          "      └─TableReader 8000.00 root  data:HashAgg",
          "        └─HashAgg 8000.00 cop[tikv]  group by:test.t.c, test.t.d, funcs:sum(test.t.a)->Column#12, funcs:count(test.t.b)->Column#13",
          "          └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ]
      }
    ]
  },
  {
    "Name": "TestMPPSinglePartitionType",
    "Cases": [
      {
        "SQL": "select * from employee where deptid>1",
        "Plan": [
          "TableReader 3333.33 root  data:ExchangeSender",
          "└─ExchangeSender 3333.33 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─Selection 3333.33 mpp[tiflash]  gt(test.employee.deptid, 1)",
          "    └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select deptid+5, empid*10  from employee where deptid>1",
        "Plan": [
          "TableReader 3333.33 root  data:ExchangeSender",
          "└─ExchangeSender 3333.33 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─Projection 3333.33 mpp[tiflash]  plus(test.employee.deptid, 5)->Column#5, mul(test.employee.empid, 10)->Column#6",
          "    └─Selection 3333.33 mpp[tiflash]  gt(test.employee.deptid, 1)",
          "      └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select count(*) from employee group by deptid+1",
        "Plan": [
          "TableReader 8000.00 root  data:ExchangeSender",
          "└─ExchangeSender 8000.00 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─Projection 8000.00 mpp[tiflash]  Column#5",
          "    └─HashAgg 8000.00 mpp[tiflash]  group by:Column#12, funcs:sum(Column#13)->Column#5",
          "      └─ExchangeReceiver 8000.00 mpp[tiflash]  ",
          "        └─ExchangeSender 8000.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: Column#12, collate: binary]",
          "          └─HashAgg 8000.00 mpp[tiflash]  group by:Column#14, funcs:count(1)->Column#13",
          "            └─Projection 10000.00 mpp[tiflash]  plus(test.employee.deptid, 1)->Column#14",
          "              └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select count(distinct deptid) a from employee",
        "Plan": [
          "TableReader 1.00 root  data:ExchangeSender",
          "└─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─Projection 1.00 mpp[tiflash]  Column#5",
          "    └─HashAgg 1.00 mpp[tiflash]  funcs:sum(Column#7)->Column#5",
          "      └─ExchangeReceiver 1.00 mpp[tiflash]  ",
          "        └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "          └─HashAgg 1.00 mpp[tiflash]  funcs:count(distinct test.employee.deptid)->Column#7",
          "            └─ExchangeReceiver 1.00 mpp[tiflash]  ",
          "              └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: test.employee.deptid, collate: binary]",
          "                └─HashAgg 1.00 mpp[tiflash]  group by:test.employee.deptid, ",
          "                  └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select * from employee join employee e1 using(deptid)",
        "Plan": [
          "TableReader 12487.50 root  data:ExchangeSender",
          "└─ExchangeSender 12487.50 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─Projection 12487.50 mpp[tiflash]  test.employee.deptid, test.employee.empid, test.employee.salary, test.employee.empid, test.employee.salary",
          "    └─HashJoin 12487.50 mpp[tiflash]  inner join, equal:[eq(test.employee.deptid, test.employee.deptid)]",
          "      ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash]  ",
          "      │ └─ExchangeSender 9990.00 mpp[tiflash]  ExchangeType: Broadcast",
          "      │   └─Selection 9990.00 mpp[tiflash]  not(isnull(test.employee.deptid))",
          "      │     └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo",
          "      └─Selection(Probe) 9990.00 mpp[tiflash]  not(isnull(test.employee.deptid))",
          "        └─TableFullScan 10000.00 mpp[tiflash] table:e1 keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select count(distinct a) from (select count(distinct deptid) a from employee) x",
        "Plan": [
          "TableReader 1.00 root  data:ExchangeSender",
          "└─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─Projection 1.00 mpp[tiflash]  Column#6",
          "    └─HashAgg 1.00 mpp[tiflash]  funcs:count(distinct Column#5)->Column#6",
          "      └─Projection 1.00 mpp[tiflash]  Column#5",
          "        └─HashAgg 1.00 mpp[tiflash]  funcs:sum(Column#8)->Column#5",
          "          └─ExchangeReceiver 1.00 mpp[tiflash]  ",
          "            └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "              └─HashAgg 1.00 mpp[tiflash]  funcs:count(distinct test.employee.deptid)->Column#8",
          "                └─ExchangeReceiver 1.00 mpp[tiflash]  ",
          "                  └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: test.employee.deptid, collate: binary]",
          "                    └─HashAgg 1.00 mpp[tiflash]  group by:test.employee.deptid, ",
          "                      └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select count(a) from (select count(distinct deptid) a, count(distinct empid) b from employee) x group by b+1",
        "Plan": [
          "TableReader 1.00 root  data:ExchangeSender",
          "└─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─Projection 1.00 mpp[tiflash]  Column#7",
          "    └─HashAgg 1.00 mpp[tiflash]  group by:Column#12, funcs:sum(Column#13)->Column#7",
          "      └─ExchangeReceiver 1.00 mpp[tiflash]  ",
          "        └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: Column#12, collate: binary]",
          "          └─HashAgg 1.00 mpp[tiflash]  group by:Column#15, funcs:count(Column#14)->Column#13",
          "            └─Projection 1.00 mpp[tiflash]  Column#5, plus(Column#6, 1)->Column#15",
          "              └─Projection 1.00 mpp[tiflash]  Column#5, Column#6",
          "                └─HashAgg 1.00 mpp[tiflash]  funcs:count(distinct test.employee.deptid)->Column#5, funcs:count(distinct test.employee.empid)->Column#6",
          "                  └─ExchangeReceiver 1.00 mpp[tiflash]  ",
          "                    └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "                      └─HashAgg 1.00 mpp[tiflash]  group by:test.employee.deptid, test.employee.empid, ",
          "                        └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select count(a) from (select count(distinct deptid) a, count(distinct empid) b from employee) x group by b",
        "Plan": [
          "TableReader 1.00 root  data:ExchangeSender",
          "└─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─Projection 1.00 mpp[tiflash]  Column#7",
          "    └─HashAgg 1.00 mpp[tiflash]  group by:Column#6, funcs:count(Column#5)->Column#7",
          "      └─Projection 1.00 mpp[tiflash]  Column#5, Column#6",
          "        └─HashAgg 1.00 mpp[tiflash]  funcs:count(distinct test.employee.deptid)->Column#5, funcs:count(distinct test.employee.empid)->Column#6",
          "          └─ExchangeReceiver 1.00 mpp[tiflash]  ",
          "            └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "              └─HashAgg 1.00 mpp[tiflash]  group by:test.employee.deptid, test.employee.empid, ",
          "                └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select * from employee join (select count(distinct deptid) a, count(distinct empid) b from employee) e1",
        "Plan": [
          "TableReader 10000.00 root  data:ExchangeSender",
          "└─ExchangeSender 10000.00 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─HashJoin 10000.00 mpp[tiflash]  CARTESIAN inner join",
          "    ├─ExchangeReceiver(Build) 1.00 mpp[tiflash]  ",
          "    │ └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: Broadcast",
          "    │   └─Projection 1.00 mpp[tiflash]  Column#9, Column#10",
          "    │     └─HashAgg 1.00 mpp[tiflash]  funcs:count(distinct test.employee.deptid)->Column#9, funcs:count(distinct test.employee.empid)->Column#10",
          "    │       └─ExchangeReceiver 1.00 mpp[tiflash]  ",
          "    │         └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "    │           └─HashAgg 1.00 mpp[tiflash]  group by:test.employee.deptid, test.employee.empid, ",
          "    │             └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo",
          "    └─TableFullScan(Probe) 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select * from employee e1 join (select count(distinct deptid) a from employee) e2 on e1.deptid = e2.a",
        "Plan": [
          "TableReader 1.25 root  data:ExchangeSender",
          "└─ExchangeSender 1.25 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─HashJoin 1.25 mpp[tiflash]  inner join, equal:[eq(test.employee.deptid, Column#9)]",
          "    ├─ExchangeReceiver(Build) 1.00 mpp[tiflash]  ",
          "    │ └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: Broadcast",
          "    │   └─Projection 1.00 mpp[tiflash]  Column#9",
          "    │     └─HashAgg 1.00 mpp[tiflash]  funcs:sum(Column#10)->Column#9",
          "    │       └─ExchangeReceiver 1.00 mpp[tiflash]  ",
          "    │         └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "    │           └─HashAgg 1.00 mpp[tiflash]  funcs:count(distinct test.employee.deptid)->Column#10",
          "    │             └─ExchangeReceiver 1.00 mpp[tiflash]  ",
          "    │               └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: test.employee.deptid, collate: binary]",
          "    │                 └─HashAgg 1.00 mpp[tiflash]  group by:test.employee.deptid, ",
          "    │                   └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo",
          "    └─Selection(Probe) 9990.00 mpp[tiflash]  not(isnull(test.employee.deptid))",
          "      └─TableFullScan 10000.00 mpp[tiflash] table:e1 keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select * from (select count(distinct deptid) a from employee) e1 join employee e2 on e1.a = e2.deptid",
        "Plan": [
          "TableReader 1.25 root  data:ExchangeSender",
          "└─ExchangeSender 1.25 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─Projection 1.25 mpp[tiflash]  Column#5, test.employee.empid, test.employee.deptid, test.employee.salary",
          "    └─HashJoin 1.25 mpp[tiflash]  inner join, equal:[eq(test.employee.deptid, Column#5)]",
          "      ├─ExchangeReceiver(Build) 1.00 mpp[tiflash]  ",
          "      │ └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: Broadcast",
          "      │   └─Projection 1.00 mpp[tiflash]  Column#5",
          "      │     └─HashAgg 1.00 mpp[tiflash]  funcs:sum(Column#10)->Column#5",
          "      │       └─ExchangeReceiver 1.00 mpp[tiflash]  ",
          "      │         └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "      │           └─HashAgg 1.00 mpp[tiflash]  funcs:count(distinct test.employee.deptid)->Column#10",
          "      │             └─ExchangeReceiver 1.00 mpp[tiflash]  ",
          "      │               └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: test.employee.deptid, collate: binary]",
          "      │                 └─HashAgg 1.00 mpp[tiflash]  group by:test.employee.deptid, ",
          "      │                   └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo",
          "      └─Selection(Probe) 9990.00 mpp[tiflash]  not(isnull(test.employee.deptid))",
          "        └─TableFullScan 10000.00 mpp[tiflash] table:e2 keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select * from (select count(distinct deptid) a from employee) e1 join (select count(distinct deptid) b from employee) e2 on e1.a=e2.b",
        "Plan": [
          "TableReader 1.00 root  data:ExchangeSender",
          "└─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─HashJoin 1.00 mpp[tiflash]  inner join, equal:[eq(Column#5, Column#10)]",
          "    ├─ExchangeReceiver(Build) 1.00 mpp[tiflash]  ",
          "    │ └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: Broadcast",
          "    │   └─Projection 1.00 mpp[tiflash]  Column#5",
          "    │     └─HashAgg 1.00 mpp[tiflash]  funcs:sum(Column#11)->Column#5",
          "    │       └─ExchangeReceiver 1.00 mpp[tiflash]  ",
          "    │         └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "    │           └─HashAgg 1.00 mpp[tiflash]  funcs:count(distinct test.employee.deptid)->Column#11",
          "    │             └─ExchangeReceiver 1.00 mpp[tiflash]  ",
          "    │               └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: test.employee.deptid, collate: binary]",
          "    │                 └─HashAgg 1.00 mpp[tiflash]  group by:test.employee.deptid, ",
          "    │                   └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo",
          "    └─Projection(Probe) 1.00 mpp[tiflash]  Column#10",
          "      └─HashAgg 1.00 mpp[tiflash]  funcs:sum(Column#12)->Column#10",
          "        └─ExchangeReceiver 1.00 mpp[tiflash]  ",
          "          └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "            └─HashAgg 1.00 mpp[tiflash]  funcs:count(distinct test.employee.deptid)->Column#12",
          "              └─ExchangeReceiver 1.00 mpp[tiflash]  ",
          "                └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: test.employee.deptid, collate: binary]",
          "                  └─HashAgg 1.00 mpp[tiflash]  group by:test.employee.deptid, ",
          "                    └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select * from employee e1 join employee e2 on e1.deptid = e2.deptid",
        "Plan": [
          "TableReader 12487.50 root  data:ExchangeSender",
          "└─ExchangeSender 12487.50 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─HashJoin 12487.50 mpp[tiflash]  inner join, equal:[eq(test.employee.deptid, test.employee.deptid)]",
          "    ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash]  ",
          "    │ └─ExchangeSender 9990.00 mpp[tiflash]  ExchangeType: Broadcast",
          "    │   └─Selection 9990.00 mpp[tiflash]  not(isnull(test.employee.deptid))",
          "    │     └─TableFullScan 10000.00 mpp[tiflash] table:e1 keep order:false, stats:pseudo",
          "    └─Selection(Probe) 9990.00 mpp[tiflash]  not(isnull(test.employee.deptid))",
          "      └─TableFullScan 10000.00 mpp[tiflash] table:e2 keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select * from (select deptid+1 d, count(empid) a from employee group by d) e1 join employee e2 on e1.d = e2.deptid",
        "Plan": [
          "TableReader 8000.00 root  data:ExchangeSender",
          "└─ExchangeSender 8000.00 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─Projection 8000.00 mpp[tiflash]  Column#6, Column#5, test.employee.empid, test.employee.deptid, test.employee.salary",
          "    └─HashJoin 8000.00 mpp[tiflash]  inner join, equal:[eq(test.employee.deptid, Column#6)]",
          "      ├─ExchangeReceiver(Build) 6400.00 mpp[tiflash]  ",
          "      │ └─ExchangeSender 6400.00 mpp[tiflash]  ExchangeType: Broadcast",
          "      │   └─Projection 6400.00 mpp[tiflash]  plus(test.employee.deptid, 1)->Column#6, Column#5",
          "      │     └─Selection 6400.00 mpp[tiflash]  not(isnull(plus(test.employee.deptid, 1)))",
          "      │       └─Projection 8000.00 mpp[tiflash]  Column#5, test.employee.deptid",
          "      │         └─HashAgg 8000.00 mpp[tiflash]  group by:Column#13, funcs:sum(Column#14)->Column#5, funcs:firstrow(Column#15)->test.employee.deptid",
          "      │           └─ExchangeReceiver 8000.00 mpp[tiflash]  ",
          "      │             └─ExchangeSender 8000.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: Column#13, collate: binary]",
          "      │               └─HashAgg 8000.00 mpp[tiflash]  group by:Column#27, funcs:count(Column#25)->Column#14, funcs:firstrow(Column#26)->Column#15",
          "      │                 └─Projection 10000.00 mpp[tiflash]  test.employee.empid, test.employee.deptid, plus(test.employee.deptid, 1)->Column#27",
          "      │                   └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo",
          "      └─Selection(Probe) 9990.00 mpp[tiflash]  not(isnull(test.employee.deptid))",
          "        └─TableFullScan 10000.00 mpp[tiflash] table:e2 keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select * from employee e1 join (select deptid+1 d, count(empid) a from employee group by d) e2 on e1.deptid = e2.d",
        "Plan": [
          "TableReader 8000.00 root  data:ExchangeSender",
          "└─ExchangeSender 8000.00 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─HashJoin 8000.00 mpp[tiflash]  inner join, equal:[eq(test.employee.deptid, Column#10)]",
          "    ├─ExchangeReceiver(Build) 6400.00 mpp[tiflash]  ",
          "    │ └─ExchangeSender 6400.00 mpp[tiflash]  ExchangeType: Broadcast",
          "    │   └─Projection 6400.00 mpp[tiflash]  plus(test.employee.deptid, 1)->Column#10, Column#9",
          "    │     └─Selection 6400.00 mpp[tiflash]  not(isnull(plus(test.employee.deptid, 1)))",
          "    │       └─Projection 8000.00 mpp[tiflash]  Column#9, test.employee.deptid",
          "    │         └─HashAgg 8000.00 mpp[tiflash]  group by:Column#13, funcs:sum(Column#14)->Column#9, funcs:firstrow(Column#15)->test.employee.deptid",
          "    │           └─ExchangeReceiver 8000.00 mpp[tiflash]  ",
          "    │             └─ExchangeSender 8000.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: Column#13, collate: binary]",
          "    │               └─HashAgg 8000.00 mpp[tiflash]  group by:Column#27, funcs:count(Column#25)->Column#14, funcs:firstrow(Column#26)->Column#15",
          "    │                 └─Projection 10000.00 mpp[tiflash]  test.employee.empid, test.employee.deptid, plus(test.employee.deptid, 1)->Column#27",
          "    │                   └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo",
          "    └─Selection(Probe) 9990.00 mpp[tiflash]  not(isnull(test.employee.deptid))",
          "      └─TableFullScan 10000.00 mpp[tiflash] table:e1 keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "TableReader 6400.00 root  data:ExchangeSender",
          "└─ExchangeSender 6400.00 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─HashJoin 6400.00 mpp[tiflash]  inner join, equal:[eq(Column#6, Column#12)]",
          "    ├─ExchangeReceiver(Build) 6400.00 mpp[tiflash]  ",
          "    │ └─ExchangeSender 6400.00 mpp[tiflash]  ExchangeType: Broadcast",
          "    │   └─Projection 6400.00 mpp[tiflash]  plus(test.employee.deptid, 1)->Column#6, Column#5",
          "    │     └─Selection 6400.00 mpp[tiflash]  not(isnull(plus(test.employee.deptid, 1)))",
          "    │       └─Projection 8000.00 mpp[tiflash]  Column#5, test.employee.deptid",
          "    │         └─HashAgg 8000.00 mpp[tiflash]  group by:Column#17, funcs:sum(Column#18)->Column#5, funcs:firstrow(Column#19)->test.employee.deptid",
          "    │           └─ExchangeReceiver 8000.00 mpp[tiflash]  ",
          "    │             └─ExchangeSender 8000.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: Column#17, collate: binary]",
          "    │               └─HashAgg 8000.00 mpp[tiflash]  group by:Column#43, funcs:count(Column#41)->Column#18, funcs:firstrow(Column#42)->Column#19",
          "    │                 └─Projection 10000.00 mpp[tiflash]  test.employee.empid, test.employee.deptid, plus(test.employee.deptid, 1)->Column#43",
          "    │                   └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo",
          "    └─Projection(Probe) 6400.00 mpp[tiflash]  plus(test.employee.deptid, 1)->Column#12, Column#11",
          "      └─Selection 6400.00 mpp[tiflash]  not(isnull(plus(test.employee.deptid, 1)))",
          "        └─Projection 8000.00 mpp[tiflash]  Column#11, test.employee.deptid",
          "          └─HashAgg 8000.00 mpp[tiflash]  group by:Column#20, funcs:sum(Column#21)->Column#11, funcs:firstrow(Column#22)->test.employee.deptid",
          "            └─ExchangeReceiver 8000.00 mpp[tiflash]  ",
          "              └─ExchangeSender 8000.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: Column#20, collate: binary]",
          "                └─HashAgg 8000.00 mpp[tiflash]  group by:Column#46, funcs:count(Column#44)->Column#21, funcs:firstrow(Column#45)->Column#22",
          "                  └─Projection 10000.00 mpp[tiflash]  test.employee.empid, test.employee.deptid, plus(test.employee.deptid, 1)->Column#46",
          "                    └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "set tidb_broadcast_join_threshold_count=1",
        "Plan": null
      },
      {
        "SQL": "set tidb_broadcast_join_threshold_size=1",
        "Plan": null
      },
      {
        "SQL": "select * from (select count(distinct deptid) a from employee) e1 join employee e2 on e1.a = e2.deptid",
        "Plan": [
          "Projection 1.25 root  Column#5, test.employee.empid, test.employee.deptid, test.employee.salary",
          "└─HashJoin 1.25 root  inner join, equal:[eq(test.employee.deptid, Column#5)]",
          "  ├─TableReader(Build) 1.00 root  data:ExchangeSender",
          "  │ └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "  │   └─Projection 1.00 mpp[tiflash]  Column#5",
          "  │     └─HashAgg 1.00 mpp[tiflash]  funcs:sum(Column#12)->Column#5",
          "  │       └─ExchangeReceiver 1.00 mpp[tiflash]  ",
          "  │         └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "  │           └─HashAgg 1.00 mpp[tiflash]  funcs:count(distinct test.employee.deptid)->Column#12",
          "  │             └─ExchangeReceiver 1.00 mpp[tiflash]  ",
          "  │               └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: test.employee.deptid, collate: binary]",
          "  │                 └─HashAgg 1.00 mpp[tiflash]  group by:test.employee.deptid, ",
          "  │                   └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo",
          "  └─TableReader(Probe) 9990.00 root  data:Selection",
          "    └─Selection 9990.00 cop[tiflash]  not(isnull(test.employee.deptid))",
          "      └─TableFullScan 10000.00 cop[tiflash] table:e2 keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select * from (select count(distinct deptid) a from employee) e1 join (select count(distinct deptid) b from employee) e2 on e1.a=e2.b",
        "Plan": [
          "HashJoin 1.00 root  inner join, equal:[eq(Column#5, Column#10)]",
          "├─TableReader(Build) 1.00 root  data:ExchangeSender",
          "│ └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "│   └─Projection 1.00 mpp[tiflash]  Column#10",
          "│     └─HashAgg 1.00 mpp[tiflash]  funcs:sum(Column#16)->Column#10",
          "│       └─ExchangeReceiver 1.00 mpp[tiflash]  ",
          "│         └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "│           └─HashAgg 1.00 mpp[tiflash]  funcs:count(distinct test.employee.deptid)->Column#16",
          "│             └─ExchangeReceiver 1.00 mpp[tiflash]  ",
          "│               └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: test.employee.deptid, collate: binary]",
          "│                 └─HashAgg 1.00 mpp[tiflash]  group by:test.employee.deptid, ",
          "│                   └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo",
          "└─TableReader(Probe) 1.00 root  data:ExchangeSender",
          "  └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "    └─Projection 1.00 mpp[tiflash]  Column#5",
          "      └─HashAgg 1.00 mpp[tiflash]  funcs:sum(Column#15)->Column#5",
          "        └─ExchangeReceiver 1.00 mpp[tiflash]  ",
          "          └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "            └─HashAgg 1.00 mpp[tiflash]  funcs:count(distinct test.employee.deptid)->Column#15",
          "              └─ExchangeReceiver 1.00 mpp[tiflash]  ",
          "                └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: test.employee.deptid, collate: binary]",
          "                  └─HashAgg 1.00 mpp[tiflash]  group by:test.employee.deptid, ",
          "                    └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select * from employee e1 join employee e2 on e1.deptid = e2.deptid",
        "Plan": [
          "TableReader 12487.50 root  data:ExchangeSender",
          "└─ExchangeSender 12487.50 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─HashJoin 12487.50 mpp[tiflash]  inner join, equal:[eq(test.employee.deptid, test.employee.deptid)]",
          "    ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash]  ",
          "    │ └─ExchangeSender 9990.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: test.employee.deptid, collate: binary]",
          "    │   └─Selection 9990.00 mpp[tiflash]  not(isnull(test.employee.deptid))",
          "    │     └─TableFullScan 10000.00 mpp[tiflash] table:e1 keep order:false, stats:pseudo",
          "    └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash]  ",
          "      └─ExchangeSender 9990.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: test.employee.deptid, collate: binary]",
          "        └─Selection 9990.00 mpp[tiflash]  not(isnull(test.employee.deptid))",
          "          └─TableFullScan 10000.00 mpp[tiflash] table:e2 keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select * from (select deptid+1 d, count(empid) a from employee group by d) e1 join employee e2 on e1.d = e2.deptid",
        "Plan": [
          "TableReader 8000.00 root  data:ExchangeSender",
          "└─ExchangeSender 8000.00 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─Projection 8000.00 mpp[tiflash]  Column#6, Column#5, test.employee.empid, test.employee.deptid, test.employee.salary",
          "    └─HashJoin 8000.00 mpp[tiflash]  inner join, equal:[eq(test.employee.deptid, Column#6)]",
          "      ├─ExchangeReceiver(Build) 6400.00 mpp[tiflash]  ",
          "      │ └─ExchangeSender 6400.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: Column#6, collate: binary]",
          "      │   └─Projection 6400.00 mpp[tiflash]  plus(test.employee.deptid, 1)->Column#6, Column#5",
          "      │     └─Selection 6400.00 mpp[tiflash]  not(isnull(plus(test.employee.deptid, 1)))",
          "      │       └─Projection 8000.00 mpp[tiflash]  Column#5, test.employee.deptid",
          "      │         └─HashAgg 8000.00 mpp[tiflash]  group by:Column#13, funcs:sum(Column#14)->Column#5, funcs:firstrow(Column#15)->test.employee.deptid",
          "      │           └─ExchangeReceiver 8000.00 mpp[tiflash]  ",
          "      │             └─ExchangeSender 8000.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: Column#13, collate: binary]",
          "      │               └─HashAgg 8000.00 mpp[tiflash]  group by:Column#29, funcs:count(Column#27)->Column#14, funcs:firstrow(Column#28)->Column#15",
          "      │                 └─Projection 10000.00 mpp[tiflash]  test.employee.empid, test.employee.deptid, plus(test.employee.deptid, 1)->Column#29",
          "      │                   └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo",
          "      └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash]  ",
          "        └─ExchangeSender 9990.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: Column#26, collate: binary]",
          "          └─Projection 9990.00 mpp[tiflash]  test.employee.empid, test.employee.deptid, test.employee.salary, cast(test.employee.deptid, bigint(20))->Column#26",
          "            └─Selection 9990.00 mpp[tiflash]  not(isnull(test.employee.deptid))",
          "              └─TableFullScan 10000.00 mpp[tiflash] table:e2 keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "select * from employee e1 join (select deptid+1 d, count(empid) a from employee group by d) e2 on e1.deptid = e2.d",
        "Plan": [
          "TableReader 8000.00 root  data:ExchangeSender",
          "└─ExchangeSender 8000.00 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─Projection 8000.00 mpp[tiflash]  test.employee.empid, test.employee.deptid, test.employee.salary, Column#10, Column#9",
          "    └─HashJoin 8000.00 mpp[tiflash]  inner join, equal:[eq(test.employee.deptid, Column#10)]",
          "      ├─ExchangeReceiver(Build) 6400.00 mpp[tiflash]  ",
          "      │ └─ExchangeSender 6400.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: Column#10, collate: binary]",
          "      │   └─Projection 6400.00 mpp[tiflash]  plus(test.employee.deptid, 1)->Column#10, Column#9",
          "      │     └─Selection 6400.00 mpp[tiflash]  not(isnull(plus(test.employee.deptid, 1)))",
          "      │       └─Projection 8000.00 mpp[tiflash]  Column#9, test.employee.deptid",
          "      │         └─HashAgg 8000.00 mpp[tiflash]  group by:Column#13, funcs:sum(Column#14)->Column#9, funcs:firstrow(Column#15)->test.employee.deptid",
          "      │           └─ExchangeReceiver 8000.00 mpp[tiflash]  ",
          "      │             └─ExchangeSender 8000.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: Column#13, collate: binary]",
          "      │               └─HashAgg 8000.00 mpp[tiflash]  group by:Column#29, funcs:count(Column#27)->Column#14, funcs:firstrow(Column#28)->Column#15",
          "      │                 └─Projection 10000.00 mpp[tiflash]  test.employee.empid, test.employee.deptid, plus(test.employee.deptid, 1)->Column#29",
          "      │                   └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo",
          "      └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash]  ",
          "        └─ExchangeSender 9990.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: Column#26, collate: binary]",
          "          └─Projection 9990.00 mpp[tiflash]  test.employee.empid, test.employee.deptid, test.employee.salary, cast(test.employee.deptid, bigint(20))->Column#26",
          "            └─Selection 9990.00 mpp[tiflash]  not(isnull(test.employee.deptid))",
          "              └─TableFullScan 10000.00 mpp[tiflash] table:e1 keep order:false, stats:pseudo"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "TableReader 6400.00 root  data:ExchangeSender",
          "└─ExchangeSender 6400.00 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─HashJoin 6400.00 mpp[tiflash]  inner join, equal:[eq(Column#6, Column#12)]",
          "    ├─ExchangeReceiver(Build) 6400.00 mpp[tiflash]  ",
          "    │ └─ExchangeSender 6400.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: Column#6, collate: binary]",
          "    │   └─Projection 6400.00 mpp[tiflash]  plus(test.employee.deptid, 1)->Column#6, Column#5",
          "    │     └─Selection 6400.00 mpp[tiflash]  not(isnull(plus(test.employee.deptid, 1)))",
          "    │       └─Projection 8000.00 mpp[tiflash]  Column#5, test.employee.deptid",
          "    │         └─HashAgg 8000.00 mpp[tiflash]  group by:Column#17, funcs:sum(Column#18)->Column#5, funcs:firstrow(Column#19)->test.employee.deptid",
          "    │           └─ExchangeReceiver 8000.00 mpp[tiflash]  ",
          "    │             └─ExchangeSender 8000.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: Column#17, collate: binary]",
          "    │               └─HashAgg 8000.00 mpp[tiflash]  group by:Column#43, funcs:count(Column#41)->Column#18, funcs:firstrow(Column#42)->Column#19",
          "    │                 └─Projection 10000.00 mpp[tiflash]  test.employee.empid, test.employee.deptid, plus(test.employee.deptid, 1)->Column#43",
          "    │                   └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo",
          "    └─ExchangeReceiver(Probe) 6400.00 mpp[tiflash]  ",
          "      └─ExchangeSender 6400.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: Column#12, collate: binary]",
          "        └─Projection 6400.00 mpp[tiflash]  plus(test.employee.deptid, 1)->Column#12, Column#11",
          "          └─Selection 6400.00 mpp[tiflash]  not(isnull(plus(test.employee.deptid, 1)))",
          "            └─Projection 8000.00 mpp[tiflash]  Column#11, test.employee.deptid",
          "              └─HashAgg 8000.00 mpp[tiflash]  group by:Column#20, funcs:sum(Column#21)->Column#11, funcs:firstrow(Column#22)->test.employee.deptid",
          "                └─ExchangeReceiver 8000.00 mpp[tiflash]  ",
          "                  └─ExchangeSender 8000.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: Column#20, collate: binary]",
          "                    └─HashAgg 8000.00 mpp[tiflash]  group by:Column#46, funcs:count(Column#44)->Column#21, funcs:firstrow(Column#45)->Column#22",
          "                      └─Projection 10000.00 mpp[tiflash]  test.employee.empid, test.employee.deptid, plus(test.employee.deptid, 1)->Column#46",
          "                        └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo"
        ]
      }
    ]
  },
  {
    "Name": "TestSemiJoinRewriteHints",
    "Cases": [
      {
        "SQL": "select /*+ SEMI_JOIN_REWRITE() */ * from t",
        "Plan": [
          "TableReader 10000.00 root  data:TableFullScan",
          "└─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Warning": "[planner:1815]The SEMI_JOIN_REWRITE hint is not used correctly, maybe it's not in a subquery or the subquery is not EXISTS clause."
      },
      {
        "SQL": "select * from t where a > (select /*+ SEMI_JOIN_REWRITE() */ min(b) from t t1 where t1.c = t.c)",
        "Plan": [
          "HashJoin 7992.00 root  inner join, equal:[eq(test.t.c, test.t.c)], other cond:gt(test.t.a, Column#9)",
          "├─Selection(Build) 6393.60 root  not(isnull(Column#9))",
          "│ └─HashAgg 7992.00 root  group by:test.t.c, funcs:min(Column#10)->Column#9, funcs:firstrow(test.t.c)->test.t.c",
          "│   └─TableReader 7992.00 root  data:HashAgg",
          "│     └─HashAgg 7992.00 cop[tikv]  group by:test.t.c, funcs:min(test.t.b)->Column#10",
          "│       └─Selection 9990.00 cop[tikv]  not(isnull(test.t.c))",
          "│         └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 9980.01 root  data:Selection",
          "  └─Selection 9980.01 cop[tikv]  not(isnull(test.t.a)), not(isnull(test.t.c))",
          "    └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Warning": "[planner:1815]The SEMI_JOIN_REWRITE hint is not used correctly, maybe it's not in a subquery or the subquery is not EXISTS clause."
      },
      {
        "SQL": "select * from t where exists (select /*+ SEMI_JOIN_REWRITE() */ 1 from t t1 where t1.a=t.a)",
        "Plan": [
          "HashJoin 9990.00 root  inner join, equal:[eq(test.t.a, test.t.a)]",
          "├─HashAgg(Build) 7992.00 root  group by:test.t.a, funcs:firstrow(test.t.a)->test.t.a",
          "│ └─TableReader 7992.00 root  data:HashAgg",
          "│   └─HashAgg 7992.00 cop[tikv]  group by:test.t.a, ",
          "│     └─Selection 9990.00 cop[tikv]  not(isnull(test.t.a))",
          "│       └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 9990.00 root  data:Selection",
          "  └─Selection 9990.00 cop[tikv]  not(isnull(test.t.a))",
          "    └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Warning": ""
      },
      {
        "SQL": "select * from t where exists (select /*+ SEMI_JOIN_REWRITE() */ t.b from t t1 where t1.a=t.a)",
        "Plan": [
          "HashJoin 9990.00 root  inner join, equal:[eq(test.t.a, test.t.a)]",
          "├─HashAgg(Build) 7992.00 root  group by:test.t.a, funcs:firstrow(test.t.a)->test.t.a",
          "│ └─TableReader 7992.00 root  data:HashAgg",
          "│   └─HashAgg 7992.00 cop[tikv]  group by:test.t.a, ",
          "│     └─Selection 9990.00 cop[tikv]  not(isnull(test.t.a))",
          "│       └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 9990.00 root  data:Selection",
          "  └─Selection 9990.00 cop[tikv]  not(isnull(test.t.a))",
          "    └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Warning": ""
      },
      {
        "SQL": "select exists(select /*+ SEMI_JOIN_REWRITE() */ * from t t1 where t1.a=t.a) from t",
        "Plan": [
          "HashJoin 10000.00 root  left outer semi join, equal:[eq(test.t.a, test.t.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Warning": "[planner:1815]SEMI_JOIN_REWRITE() is inapplicable for LeftOuterSemiJoin."
      },
      {
        "SQL": "select * from t where exists (select /*+ SEMI_JOIN_REWRITE() */ 1 from t t1 where t1.a > t.a)",
        "Plan": [
          "HashJoin 7992.00 root  CARTESIAN semi join, other cond:gt(test.t.a, test.t.a)",
          "├─TableReader(Build) 9990.00 root  data:Selection",
          "│ └─Selection 9990.00 cop[tikv]  not(isnull(test.t.a))",
          "│   └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 9990.00 root  data:Selection",
          "  └─Selection 9990.00 cop[tikv]  not(isnull(test.t.a))",
          "    └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Warning": "[planner:1815]SEMI_JOIN_REWRITE() is inapplicable for SemiJoin with left conditions or other conditions."
      }
    ]
  },
  {
    "Name": "TestHJBuildAndProbeHint",
    "Cases": [
      {
        "SQL": "select /*+ hash_join_build(t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_probe(t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_build(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_probe(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_build(t2) */ t1.a, t2.a from t1 left join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  left outer join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 <nil>"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_probe(t2) */ t1.a, t2.a from t1 left join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  left outer join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 <nil>"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_build(t1) */ t1.a, t2.a from t1 left join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  left outer join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 <nil>"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_probe(t1) */ t1.a, t2.a from t1 left join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  left outer join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 <nil>"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_build(t2) */ t1.a, t2.a from t1 right join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  right outer join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "<nil> 2"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_probe(t2) */ t1.a, t2.a from t1 right join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  right outer join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "<nil> 2"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_build(t1) */ t1.a, t2.a from t1 right join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  right outer join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "<nil> 2"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_probe(t1) */ t1.a, t2.a from t1 right join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  right outer join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "<nil> 2"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_build(t2) */ t1.a, t2.a from t1 straight_join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_probe(t2) */ t1.a, t2.a from t1 straight_join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_build(t1) */ t1.a, t2.a from t1 straight_join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_probe(t1) */ t1.a, t2.a from t1 straight_join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_build(t2) */ t1.a, t2.a from t1 cross join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_probe(t2) */ t1.a, t2.a from t1 cross join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_build(t1) */ t1.a, t2.a from t1 cross join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_probe(t1) */ t1.a, t2.a from t1 cross join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_build(t1) */ * from t1 where t1.a in (select t2.a from t2 where t1.b = t2.b)",
        "Plan": [
          "HashJoin 8000.00 root  semi join, equal:[eq(test.t1.b, test.t2.b) eq(test.t1.a, test.t2.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for semi join, please check the hint"
        ]
      },
      {
        "SQL": "select /*+ hash_join_probe(t1) */ * from t1 where t1.a in (select t2.a from t2 where t1.b = t2.b)",
        "Plan": [
          "HashJoin 8000.00 root  semi join, equal:[eq(test.t1.b, test.t2.b) eq(test.t1.a, test.t2.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for semi join, please check the hint"
        ]
      },
      {
        "SQL": "select /*+ hash_join_build(t2@sel_2) */ * from t1 where t1.a in (select t2.a from t2 where t1.b = t2.b)",
        "Plan": [
          "HashJoin 8000.00 root  semi join, equal:[eq(test.t1.b, test.t2.b) eq(test.t1.a, test.t2.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for semi join, please check the hint"
        ]
      },
      {
        "SQL": "select /*+ hash_join_probe(t2@sel_2) */ * from t1 where t1.a in (select t2.a from t2 where t1.b = t2.b)",
        "Plan": [
          "HashJoin 8000.00 root  semi join, equal:[eq(test.t1.b, test.t2.b) eq(test.t1.a, test.t2.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for semi join, please check the hint"
        ]
      },
      {
        "SQL": "select /*+ hash_join_build(t1) */ * from t1 where t1.a not in (select t2.a from t2 where t1.b = t2.b)",
        "Plan": [
          "HashJoin 8000.00 root  anti semi join, equal:[eq(test.t1.b, test.t2.b) eq(test.t1.a, test.t2.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "2 2"
        ],
        "Warning": [
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for anti semi join, please check the hint"
        ]
      },
      {
        "SQL": "select /*+ hash_join_probe(t1) */ * from t1 where t1.a not in (select t2.a from t2 where t1.b = t2.b)",
        "Plan": [
          "HashJoin 8000.00 root  anti semi join, equal:[eq(test.t1.b, test.t2.b) eq(test.t1.a, test.t2.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "2 2"
        ],
        "Warning": [
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for anti semi join, please check the hint"
        ]
      },
      {
        "SQL": "select /*+ hash_join_build(t2@sel_2) */ * from t1 where t1.a not in (select t2.a from t2 where t1.b = t2.b)",
        "Plan": [
          "HashJoin 8000.00 root  anti semi join, equal:[eq(test.t1.b, test.t2.b) eq(test.t1.a, test.t2.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "2 2"
        ],
        "Warning": [
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for anti semi join, please check the hint"
        ]
      },
      {
        "SQL": "select /*+ hash_join_probe(t2@sel_2) */ * from t1 where t1.a not in (select t2.a from t2 where t1.b = t2.b)",
        "Plan": [
          "HashJoin 8000.00 root  anti semi join, equal:[eq(test.t1.b, test.t2.b) eq(test.t1.a, test.t2.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "2 2"
        ],
        "Warning": [
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for anti semi join, please check the hint"
        ]
      },
      {
        "SQL": "select /*+ hash_join_build(t1) */ sum(t1.a in (select a from t2)) from t1",
        "Plan": [
          "HashAgg 1.00 root  funcs:sum(Column#9)->Column#8",
          "└─Projection 10000.00 root  cast(Column#7, decimal(3,0) BINARY)->Column#9",
          "  └─MergeJoin 10000.00 root  left outer semi join, left key:test.t1.a, right key:test.t2.a",
          "    ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "    │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo",
          "    └─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "      └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo"
        ],
        "Result": [
          "2"
        ],
        "Warning": [
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for left outer semi join, please check the hint",
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for left outer semi join, please check the hint"
        ]
      },
      {
        "SQL": "select /*+ hash_join_probe(t1) */ sum(t1.a in (select a from t2)) from t1",
        "Plan": [
          "HashAgg 1.00 root  funcs:sum(Column#9)->Column#8",
          "└─Projection 10000.00 root  cast(Column#7, decimal(3,0) BINARY)->Column#9",
          "  └─MergeJoin 10000.00 root  left outer semi join, left key:test.t1.a, right key:test.t2.a",
          "    ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "    │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo",
          "    └─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "      └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo"
        ],
        "Result": [
          "2"
        ],
        "Warning": [
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for left outer semi join, please check the hint",
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for left outer semi join, please check the hint"
        ]
      },
      {
        "SQL": "select /*+ hash_join_build(t2@sel_2) */ sum(t1.a in (select a from t2)) from t1",
        "Plan": [
          "HashAgg 1.00 root  funcs:sum(Column#9)->Column#8",
          "└─Projection 10000.00 root  cast(Column#7, decimal(3,0) BINARY)->Column#9",
          "  └─MergeJoin 10000.00 root  left outer semi join, left key:test.t1.a, right key:test.t2.a",
          "    ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "    │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo",
          "    └─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "      └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo"
        ],
        "Result": [
          "2"
        ],
        "Warning": [
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for left outer semi join, please check the hint",
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for left outer semi join, please check the hint"
        ]
      },
      {
        "SQL": "select /*+ hash_join_probe(t2@sel_2) */ sum(t1.a in (select a from t2)) from t1",
        "Plan": [
          "HashAgg 1.00 root  funcs:sum(Column#9)->Column#8",
          "└─Projection 10000.00 root  cast(Column#7, decimal(3,0) BINARY)->Column#9",
          "  └─MergeJoin 10000.00 root  left outer semi join, left key:test.t1.a, right key:test.t2.a",
          "    ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "    │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo",
          "    └─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "      └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo"
        ],
        "Result": [
          "2"
        ],
        "Warning": [
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for left outer semi join, please check the hint",
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for left outer semi join, please check the hint"
        ]
      },
      {
        "SQL": "select /*+ hash_join_build(t1) */ sum(t1.a not in (select a from t2)) from t1",
        "Plan": [
          "HashAgg 1.00 root  funcs:sum(Column#9)->Column#8",
          "└─Projection 10000.00 root  cast(Column#7, decimal(3,0) BINARY)->Column#9",
          "  └─MergeJoin 10000.00 root  anti left outer semi join, left key:test.t1.a, right key:test.t2.a",
          "    ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "    │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo",
          "    └─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "      └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo"
        ],
        "Result": [
          "0"
        ],
        "Warning": [
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for anti left outer semi join, please check the hint",
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for anti left outer semi join, please check the hint"
        ]
      },
      {
        "SQL": "select /*+ hash_join_probe(t1) */ sum(t1.a not in (select a from t2)) from t1",
        "Plan": [
          "HashAgg 1.00 root  funcs:sum(Column#9)->Column#8",
          "└─Projection 10000.00 root  cast(Column#7, decimal(3,0) BINARY)->Column#9",
          "  └─MergeJoin 10000.00 root  anti left outer semi join, left key:test.t1.a, right key:test.t2.a",
          "    ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "    │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo",
          "    └─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "      └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo"
        ],
        "Result": [
          "0"
        ],
        "Warning": [
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for anti left outer semi join, please check the hint",
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for anti left outer semi join, please check the hint"
        ]
      },
      {
        "SQL": "select /*+ hash_join_build(t2@sel_2) */ sum(t1.a not in (select a from t2)) from t1",
        "Plan": [
          "HashAgg 1.00 root  funcs:sum(Column#9)->Column#8",
          "└─Projection 10000.00 root  cast(Column#7, decimal(3,0) BINARY)->Column#9",
          "  └─MergeJoin 10000.00 root  anti left outer semi join, left key:test.t1.a, right key:test.t2.a",
          "    ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "    │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo",
          "    └─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "      └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo"
        ],
        "Result": [
          "0"
        ],
        "Warning": [
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for anti left outer semi join, please check the hint",
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for anti left outer semi join, please check the hint"
        ]
      },
      {
        "SQL": "select /*+ hash_join_probe(t2@sel_2) */ sum(t1.a not in (select a from t2)) from t1",
        "Plan": [
          "HashAgg 1.00 root  funcs:sum(Column#9)->Column#8",
          "└─Projection 10000.00 root  cast(Column#7, decimal(3,0) BINARY)->Column#9",
          "  └─MergeJoin 10000.00 root  anti left outer semi join, left key:test.t1.a, right key:test.t2.a",
          "    ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "    │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo",
          "    └─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "      └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo"
        ],
        "Result": [
          "0"
        ],
        "Warning": [
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for anti left outer semi join, please check the hint",
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for anti left outer semi join, please check the hint"
        ]
      },
      {
        "SQL": "select /*+ hash_join_probe(t2, t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 There are no matching table names for (t2) in optimizer hint /*+ HASH_JOIN_PROBE(t2, t2) */. Maybe you can use the table alias name"
        ]
      },
      {
        "SQL": "select /*+ hash_join_build(t1, t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 There are no matching table names for (t1) in optimizer hint /*+ HASH_JOIN_BUILD(t1, t1) */. Maybe you can use the table alias name"
        ]
      },
      {
        "SQL": "select /*+ hash_join_probe(tt) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 There are no matching table names for (tt) in optimizer hint /*+ HASH_JOIN_PROBE(tt) */. Maybe you can use the table alias name"
        ]
      },
      {
        "SQL": "select /*+ hash_join_build(tt) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 There are no matching table names for (tt) in optimizer hint /*+ HASH_JOIN_BUILD(tt) */. Maybe you can use the table alias name"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_probe(t2, t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 Join hints are conflict, you can only specify one type of join"
        ]
      },
      {
        "SQL": "select /*+ hash_join_build(t1, t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 Join hints are conflict, you can only specify one type of join"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 Join hints are conflict, you can only specify one type of join"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 Join hints are conflict, you can only specify one type of join"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 15625.00 root  inner join, equal:[eq(test.t3.a, test.t2.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
          "└─HashJoin(Probe) 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "  ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "  │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "  └─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "    └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 leading hint is inapplicable, check the join type or the join algorithm hint",
          "Warning 1815 leading hint is inapplicable, check if the leading hint table is valid"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 15625.00 root  inner join, equal:[eq(test.t3.a, test.t2.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
          "└─HashJoin(Probe) 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "  ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "  │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "  └─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "    └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 leading hint is inapplicable, check the join type or the join algorithm hint",
          "Warning 1815 leading hint is inapplicable, check if the leading hint table is valid"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 15625.00 root  inner join, equal:[eq(test.t3.a, test.t2.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
          "└─HashJoin(Probe) 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "  ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "  │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "  └─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "    └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 leading hint is inapplicable, check the join type or the join algorithm hint",
          "Warning 1815 leading hint is inapplicable, check if the leading hint table is valid"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 15625.00 root  inner join, equal:[eq(test.t3.a, test.t2.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
          "└─HashJoin(Probe) 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "  ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "  │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "  └─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "    └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 leading hint is inapplicable, check the join type or the join algorithm hint",
          "Warning 1815 leading hint is inapplicable, check if the leading hint table is valid"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 15625.00 root  inner join, equal:[eq(test.t2.a, test.t3.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
          "└─HashJoin(Probe) 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "  ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "  │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "  └─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "    └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 15625.00 root  inner join, equal:[eq(test.t2.a, test.t3.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
          "└─HashJoin(Probe) 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "  ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "  │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "  └─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "    └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 15625.00 root  inner join, equal:[eq(test.t2.a, test.t3.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
          "└─HashJoin(Probe) 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "  ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "  │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "  └─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "    └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 15625.00 root  inner join, equal:[eq(test.t2.a, test.t3.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
          "└─HashJoin(Probe) 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "  ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "  │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "  └─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "    └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 Join hints are conflict, you can only specify one type of join"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 Join hints are conflict, you can only specify one type of join"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 Join hints are conflict, you can only specify one type of join"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 Join hints are conflict, you can only specify one type of join"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 Join hints are conflict, you can only specify one type of join"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 Join hints are conflict, you can only specify one type of join"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 Join hints are conflict, you can only specify one type of join"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 Join hints are conflict, you can only specify one type of join"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 Join hints are conflict, you can only specify one type of join"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 Join hints are conflict, you can only specify one type of join"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 Join hints are conflict, you can only specify one type of join"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 Join hints are conflict, you can only specify one type of join"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 Join hints are conflict, you can only specify one type of join"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 Join hints are conflict, you can only specify one type of join"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 Join hints are conflict, you can only specify one type of join"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 Join hints are conflict, you can only specify one type of join"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 Join hints are conflict, you can only specify one type of join"
        ]
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": [
          "Warning 1815 Join hints are conflict, you can only specify one type of join"
        ]
      },
      {
        "SQL": "SELECT * FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.a = t1.a);",
        "Plan": [
          "MergeJoin 8000.00 root  semi join, left key:test.t1.a, right key:test.t2.a",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 2"
        ],
        "Warning": null
      },
      {
        "SQL": "SELECT /*+ hash_join_probe(t1) */ * FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.a = t1.a);",
        "Plan": [
          "MergeJoin 8000.00 root  semi join, left key:test.t1.a, right key:test.t2.a",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 2"
        ],
        "Warning": [
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for semi join, please check the hint"
        ]
      },
      {
        "SQL": "SELECT /*+ hash_join_probe(t2@sel_2) */ * FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.a = t1.a);",
        "Plan": [
          "MergeJoin 8000.00 root  semi join, left key:test.t1.a, right key:test.t2.a",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 2"
        ],
        "Warning": [
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for semi join, please check the hint"
        ]
      },
      {
        "SQL": "SELECT /*+ hash_join_probe(t1) */ * FROM t1 WHERE EXISTS (SELECT /*+ SEMI_JOIN_REWRITE() */ 1 FROM t2 WHERE t2.a = t1.a);",
        "Plan": [
          "HashJoin 10000.00 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
          "├─StreamAgg(Build) 8000.00 root  group by:test.t2.a, funcs:firstrow(test.t2.a)->test.t2.a",
          "│ └─TableReader 8000.00 root  data:StreamAgg",
          "│   └─StreamAgg 8000.00 cop[tikv]  group by:test.t2.a, ",
          "│     └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 2"
        ],
        "Warning": null
      },
      {
        "SQL": "SELECT /*+ hash_join_probe(t2@sel_2) */ * FROM t1 WHERE EXISTS (SELECT /*+ SEMI_JOIN_REWRITE() */ 1 FROM t2 WHERE t2.a = t1.a);",
        "Plan": [
          "HashJoin 10000.00 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─StreamAgg(Probe) 8000.00 root  group by:test.t2.a, funcs:firstrow(test.t2.a)->test.t2.a",
          "  └─TableReader 8000.00 root  data:StreamAgg",
          "    └─StreamAgg 8000.00 cop[tikv]  group by:test.t2.a, ",
          "      └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 2"
        ],
        "Warning": null
      },
      {
        "SQL": "SELECT /*+ hash_join_build(t1) */ * FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.a = t1.a);",
        "Plan": [
          "MergeJoin 8000.00 root  semi join, left key:test.t1.a, right key:test.t2.a",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 2"
        ],
        "Warning": [
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for semi join, please check the hint"
        ]
      },
      {
        "SQL": "SELECT /*+ hash_join_build(t2@sel_2) */ * FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.a = t1.a);",
        "Plan": [
          "MergeJoin 8000.00 root  semi join, left key:test.t1.a, right key:test.t2.a",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 2"
        ],
        "Warning": [
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for semi join, please check the hint"
        ]
      },
      {
        "SQL": "SELECT /*+ hash_join_build(t1) */ * FROM t1 WHERE EXISTS (SELECT /*+ SEMI_JOIN_REWRITE() */ 1 FROM t2 WHERE t2.a = t1.a);",
        "Plan": [
          "HashJoin 10000.00 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─StreamAgg(Probe) 8000.00 root  group by:test.t2.a, funcs:firstrow(test.t2.a)->test.t2.a",
          "  └─TableReader 8000.00 root  data:StreamAgg",
          "    └─StreamAgg 8000.00 cop[tikv]  group by:test.t2.a, ",
          "      └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 2"
        ],
        "Warning": null
      },
      {
        "SQL": "SELECT /*+ hash_join_build(t2@sel_2) */ * FROM t1 WHERE EXISTS (SELECT /*+ SEMI_JOIN_REWRITE() */ 1 FROM t2 WHERE t2.a = t1.a);",
        "Plan": [
          "HashJoin 10000.00 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
          "├─StreamAgg(Build) 8000.00 root  group by:test.t2.a, funcs:firstrow(test.t2.a)->test.t2.a",
          "│ └─TableReader 8000.00 root  data:StreamAgg",
          "│   └─StreamAgg 8000.00 cop[tikv]  group by:test.t2.a, ",
          "│     └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 2"
        ],
        "Warning": null
      },
      {
        "SQL": "SELECT t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);",
        "Plan": [
          "MergeJoin 12500.00 root  inner join, left key:test.t1.a, right key:test.t2.a",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 2"
        ],
        "Warning": null
      },
      {
        "SQL": "SELECT /*+ hash_join_build(t1) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 2"
        ],
        "Warning": null
      },
      {
        "SQL": "SELECT /*+ hash_join_probe(t1) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 2"
        ],
        "Warning": null
      },
      {
        "SQL": "SELECT /*+ hash_join_build(t2@sel_2) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 2"
        ],
        "Warning": null
      },
      {
        "SQL": "SELECT /*+ hash_join_probe(t2@sel_2) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 2"
        ],
        "Warning": null
      },
      {
        "SQL": "SELECT /*+ USE_TOJA(TRUE) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);",
        "Plan": [
          "MergeJoin 12500.00 root  inner join, left key:test.t1.a, right key:test.t2.a",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 2"
        ],
        "Warning": null
      },
      {
        "SQL": "SELECT /*+ USE_TOJA(TRUE) hash_join_build(t1) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 2"
        ],
        "Warning": null
      },
      {
        "SQL": "SELECT /*+ USE_TOJA(TRUE) hash_join_probe(t1) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 2"
        ],
        "Warning": null
      },
      {
        "SQL": "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);",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 2"
        ],
        "Warning": null
      },
      {
        "SQL": "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);",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 2"
        ],
        "Warning": null
      },
      {
        "SQL": "SELECT /*+ USE_TOJA(false) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);",
        "Plan": [
          "MergeJoin 8000.00 root  semi join, left key:test.t1.a, right key:test.t2.a",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 2"
        ],
        "Warning": null
      },
      {
        "SQL": "SELECT /*+ USE_TOJA(false) hash_join_build(t1) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);",
        "Plan": [
          "MergeJoin 8000.00 root  semi join, left key:test.t1.a, right key:test.t2.a",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 2"
        ],
        "Warning": [
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for semi join, please check the hint"
        ]
      },
      {
        "SQL": "SELECT /*+ USE_TOJA(false) hash_join_probe(t1) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2);",
        "Plan": [
          "MergeJoin 8000.00 root  semi join, left key:test.t1.a, right key:test.t2.a",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 2"
        ],
        "Warning": [
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for semi join, please check the hint"
        ]
      },
      {
        "SQL": "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);",
        "Plan": [
          "MergeJoin 8000.00 root  semi join, left key:test.t1.a, right key:test.t2.a",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 2"
        ],
        "Warning": [
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for semi join, please check the hint"
        ]
      },
      {
        "SQL": "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);",
        "Plan": [
          "MergeJoin 8000.00 root  semi join, left key:test.t1.a, right key:test.t2.a",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 2"
        ],
        "Warning": [
          "Warning 1815 We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for semi join, please check the hint"
        ]
      }
    ]
  },
  {
    "Name": "TestHJBuildAndProbeHint4StaticPartitionTable",
    "Cases": [
      {
        "SQL": "select /*+ hash_join_build(t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 49900.05 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─PartitionUnion(Build) 49900.05 root  ",
          "│ ├─TableReader 9980.01 root  data:Selection",
          "│ │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t2.a)), not(isnull(test.t2.b))",
          "│ │   └─TableFullScan 10000.00 cop[tikv] table:t2, partition:p0 keep order:false, stats:pseudo",
          "│ ├─TableReader 9980.01 root  data:Selection",
          "│ │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t2.a)), not(isnull(test.t2.b))",
          "│ │   └─TableFullScan 10000.00 cop[tikv] table:t2, partition:p1 keep order:false, stats:pseudo",
          "│ ├─TableReader 9980.01 root  data:Selection",
          "│ │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t2.a)), not(isnull(test.t2.b))",
          "│ │   └─TableFullScan 10000.00 cop[tikv] table:t2, partition:p2 keep order:false, stats:pseudo",
          "│ ├─TableReader 9980.01 root  data:Selection",
          "│ │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t2.a)), not(isnull(test.t2.b))",
          "│ │   └─TableFullScan 10000.00 cop[tikv] table:t2, partition:p3 keep order:false, stats:pseudo",
          "│ └─TableReader 9980.01 root  data:Selection",
          "│   └─Selection 9980.01 cop[tikv]  not(isnull(test.t2.a)), not(isnull(test.t2.b))",
          "│     └─TableFullScan 10000.00 cop[tikv] table:t2, partition:p4 keep order:false, stats:pseudo",
          "└─PartitionUnion(Probe) 39920.04 root  ",
          "  ├─TableReader 9980.01 root  data:Selection",
          "  │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
          "  │   └─TableFullScan 10000.00 cop[tikv] table:t1, partition:p0 keep order:false, stats:pseudo",
          "  ├─TableReader 9980.01 root  data:Selection",
          "  │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
          "  │   └─TableFullScan 10000.00 cop[tikv] table:t1, partition:p1 keep order:false, stats:pseudo",
          "  ├─TableReader 9980.01 root  data:Selection",
          "  │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
          "  │   └─TableFullScan 10000.00 cop[tikv] table:t1, partition:p2 keep order:false, stats:pseudo",
          "  └─TableReader 9980.01 root  data:Selection",
          "    └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
          "      └─TableFullScan 10000.00 cop[tikv] table:t1, partition:p3 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_probe(t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 49900.05 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─PartitionUnion(Build) 39920.04 root  ",
          "│ ├─TableReader 9980.01 root  data:Selection",
          "│ │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
          "│ │   └─TableFullScan 10000.00 cop[tikv] table:t1, partition:p0 keep order:false, stats:pseudo",
          "│ ├─TableReader 9980.01 root  data:Selection",
          "│ │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
          "│ │   └─TableFullScan 10000.00 cop[tikv] table:t1, partition:p1 keep order:false, stats:pseudo",
          "│ ├─TableReader 9980.01 root  data:Selection",
          "│ │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
          "│ │   └─TableFullScan 10000.00 cop[tikv] table:t1, partition:p2 keep order:false, stats:pseudo",
          "│ └─TableReader 9980.01 root  data:Selection",
          "│   └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
          "│     └─TableFullScan 10000.00 cop[tikv] table:t1, partition:p3 keep order:false, stats:pseudo",
          "└─PartitionUnion(Probe) 49900.05 root  ",
          "  ├─TableReader 9980.01 root  data:Selection",
          "  │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t2.a)), not(isnull(test.t2.b))",
          "  │   └─TableFullScan 10000.00 cop[tikv] table:t2, partition:p0 keep order:false, stats:pseudo",
          "  ├─TableReader 9980.01 root  data:Selection",
          "  │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t2.a)), not(isnull(test.t2.b))",
          "  │   └─TableFullScan 10000.00 cop[tikv] table:t2, partition:p1 keep order:false, stats:pseudo",
          "  ├─TableReader 9980.01 root  data:Selection",
          "  │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t2.a)), not(isnull(test.t2.b))",
          "  │   └─TableFullScan 10000.00 cop[tikv] table:t2, partition:p2 keep order:false, stats:pseudo",
          "  ├─TableReader 9980.01 root  data:Selection",
          "  │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t2.a)), not(isnull(test.t2.b))",
          "  │   └─TableFullScan 10000.00 cop[tikv] table:t2, partition:p3 keep order:false, stats:pseudo",
          "  └─TableReader 9980.01 root  data:Selection",
          "    └─Selection 9980.01 cop[tikv]  not(isnull(test.t2.a)), not(isnull(test.t2.b))",
          "      └─TableFullScan 10000.00 cop[tikv] table:t2, partition:p4 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_build(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 49900.05 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─PartitionUnion(Build) 39920.04 root  ",
          "│ ├─TableReader 9980.01 root  data:Selection",
          "│ │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
          "│ │   └─TableFullScan 10000.00 cop[tikv] table:t1, partition:p0 keep order:false, stats:pseudo",
          "│ ├─TableReader 9980.01 root  data:Selection",
          "│ │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
          "│ │   └─TableFullScan 10000.00 cop[tikv] table:t1, partition:p1 keep order:false, stats:pseudo",
          "│ ├─TableReader 9980.01 root  data:Selection",
          "│ │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
          "│ │   └─TableFullScan 10000.00 cop[tikv] table:t1, partition:p2 keep order:false, stats:pseudo",
          "│ └─TableReader 9980.01 root  data:Selection",
          "│   └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
          "│     └─TableFullScan 10000.00 cop[tikv] table:t1, partition:p3 keep order:false, stats:pseudo",
          "└─PartitionUnion(Probe) 49900.05 root  ",
          "  ├─TableReader 9980.01 root  data:Selection",
          "  │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t2.a)), not(isnull(test.t2.b))",
          "  │   └─TableFullScan 10000.00 cop[tikv] table:t2, partition:p0 keep order:false, stats:pseudo",
          "  ├─TableReader 9980.01 root  data:Selection",
          "  │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t2.a)), not(isnull(test.t2.b))",
          "  │   └─TableFullScan 10000.00 cop[tikv] table:t2, partition:p1 keep order:false, stats:pseudo",
          "  ├─TableReader 9980.01 root  data:Selection",
          "  │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t2.a)), not(isnull(test.t2.b))",
          "  │   └─TableFullScan 10000.00 cop[tikv] table:t2, partition:p2 keep order:false, stats:pseudo",
          "  ├─TableReader 9980.01 root  data:Selection",
          "  │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t2.a)), not(isnull(test.t2.b))",
          "  │   └─TableFullScan 10000.00 cop[tikv] table:t2, partition:p3 keep order:false, stats:pseudo",
          "  └─TableReader 9980.01 root  data:Selection",
          "    └─Selection 9980.01 cop[tikv]  not(isnull(test.t2.a)), not(isnull(test.t2.b))",
          "      └─TableFullScan 10000.00 cop[tikv] table:t2, partition:p4 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_probe(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 49900.05 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─PartitionUnion(Build) 49900.05 root  ",
          "│ ├─TableReader 9980.01 root  data:Selection",
          "│ │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t2.a)), not(isnull(test.t2.b))",
          "│ │   └─TableFullScan 10000.00 cop[tikv] table:t2, partition:p0 keep order:false, stats:pseudo",
          "│ ├─TableReader 9980.01 root  data:Selection",
          "│ │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t2.a)), not(isnull(test.t2.b))",
          "│ │   └─TableFullScan 10000.00 cop[tikv] table:t2, partition:p1 keep order:false, stats:pseudo",
          "│ ├─TableReader 9980.01 root  data:Selection",
          "│ │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t2.a)), not(isnull(test.t2.b))",
          "│ │   └─TableFullScan 10000.00 cop[tikv] table:t2, partition:p2 keep order:false, stats:pseudo",
          "│ ├─TableReader 9980.01 root  data:Selection",
          "│ │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t2.a)), not(isnull(test.t2.b))",
          "│ │   └─TableFullScan 10000.00 cop[tikv] table:t2, partition:p3 keep order:false, stats:pseudo",
          "│ └─TableReader 9980.01 root  data:Selection",
          "│   └─Selection 9980.01 cop[tikv]  not(isnull(test.t2.a)), not(isnull(test.t2.b))",
          "│     └─TableFullScan 10000.00 cop[tikv] table:t2, partition:p4 keep order:false, stats:pseudo",
          "└─PartitionUnion(Probe) 39920.04 root  ",
          "  ├─TableReader 9980.01 root  data:Selection",
          "  │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
          "  │   └─TableFullScan 10000.00 cop[tikv] table:t1, partition:p0 keep order:false, stats:pseudo",
          "  ├─TableReader 9980.01 root  data:Selection",
          "  │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
          "  │   └─TableFullScan 10000.00 cop[tikv] table:t1, partition:p1 keep order:false, stats:pseudo",
          "  ├─TableReader 9980.01 root  data:Selection",
          "  │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
          "  │   └─TableFullScan 10000.00 cop[tikv] table:t1, partition:p2 keep order:false, stats:pseudo",
          "  └─TableReader 9980.01 root  data:Selection",
          "    └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
          "      └─TableFullScan 10000.00 cop[tikv] table:t1, partition:p3 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      }
    ]
  },
  {
    "Name": "TestHJBuildAndProbeHint4DynamicPartitionTable",
    "Cases": [
      {
        "SQL": "select /*+ hash_join_build(t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12475.01 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 9980.01 root partition:all data:Selection",
          "│ └─Selection 9980.01 cop[tikv]  not(isnull(test.t2.a)), not(isnull(test.t2.b))",
          "│   └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 9980.01 root partition:all data:Selection",
          "  └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
          "    └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_probe(t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12475.01 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 9980.01 root partition:all data:Selection",
          "│ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
          "│   └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 9980.01 root partition:all data:Selection",
          "  └─Selection 9980.01 cop[tikv]  not(isnull(test.t2.a)), not(isnull(test.t2.b))",
          "    └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_build(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12475.01 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 9980.01 root partition:all data:Selection",
          "│ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
          "│   └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 9980.01 root partition:all data:Selection",
          "  └─Selection 9980.01 cop[tikv]  not(isnull(test.t2.a)), not(isnull(test.t2.b))",
          "    └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select /*+ hash_join_probe(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12475.01 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 9980.01 root partition:all data:Selection",
          "│ └─Selection 9980.01 cop[tikv]  not(isnull(test.t2.a)), not(isnull(test.t2.b))",
          "│   └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 9980.01 root partition:all data:Selection",
          "  └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
          "    └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1"
        ],
        "Warning": null
      }
    ]
  },
  {
    "Name": "TestHJBuildAndProbeHint4TiFlash",
    "Cases": [
      {
        "SQL": "select /*+ hash_join_build(t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tiflash] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tiflash] table:t1 keep order:false, stats:pseudo"
        ],
        "Warning": [
          "Warning 1105 MPP mode may be blocked because you have used hint to specify a join algorithm which is not supported by mpp now.",
          "Warning 1105 MPP mode may be blocked because you have used hint to specify a join algorithm which is not supported by mpp now."
        ]
      },
      {
        "SQL": "select /*+ hash_join_probe(t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tiflash] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tiflash] table:t2 keep order:false, stats:pseudo"
        ],
        "Warning": [
          "Warning 1105 MPP mode may be blocked because you have used hint to specify a join algorithm which is not supported by mpp now.",
          "Warning 1105 MPP mode may be blocked because you have used hint to specify a join algorithm which is not supported by mpp now."
        ]
      },
      {
        "SQL": "select /*+ hash_join_build(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tiflash] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tiflash] table:t2 keep order:false, stats:pseudo"
        ],
        "Warning": [
          "Warning 1105 MPP mode may be blocked because you have used hint to specify a join algorithm which is not supported by mpp now.",
          "Warning 1105 MPP mode may be blocked because you have used hint to specify a join algorithm which is not supported by mpp now."
        ]
      },
      {
        "SQL": "select /*+ hash_join_probe(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b",
        "Plan": [
          "HashJoin 12500.00 root  inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tiflash] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tiflash] table:t1 keep order:false, stats:pseudo"
        ],
        "Warning": [
          "Warning 1105 MPP mode may be blocked because you have used hint to specify a join algorithm which is not supported by mpp now.",
          "Warning 1105 MPP mode may be blocked because you have used hint to specify a join algorithm which is not supported by mpp now."
        ]
      }
    ]
  },
  {
    "Name": "TestNoDecorrelateHint",
    "Cases": [
      {
        "SQL": "select /*+ no_decorrelate() */ * from t1",
        "Plan": [
          "TableReader 10000.00 root  data:TableFullScan",
          "└─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 2"
        ],
        "Warning": [
          "Warning 1815 NO_DECORRELATE() is inapplicable because it's not in an IN subquery, an EXISTS subquery, an ANY/ALL/SOME subquery or a scalar subquery."
        ]
      },
      {
        "SQL": "select * from t1, (select /*+ no_decorrelate() */ * from t2) n",
        "Plan": [
          "HashJoin 100000000.00 root  CARTESIAN inner join",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1 1 1",
          "1 1 2 1",
          "2 2 1 1",
          "2 2 2 1"
        ],
        "Warning": [
          "Warning 1815 NO_DECORRELATE() is inapplicable because it's not in an IN subquery, an EXISTS subquery, an ANY/ALL/SOME subquery or a scalar subquery."
        ]
      },
      {
        "SQL": "select a+1, b-1 from (select /*+ no_decorrelate() */ * from t1) n",
        "Plan": [
          "Projection 10000.00 root  plus(test.t1.a, 1)->Column#4, minus(test.t1.b, 1)->Column#5",
          "└─TableReader 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "2 0",
          "3 1"
        ],
        "Warning": [
          "Warning 1815 NO_DECORRELATE() is inapplicable because it's not in an IN subquery, an EXISTS subquery, an ANY/ALL/SOME subquery or a scalar subquery."
        ]
      },
      {
        "SQL": "select exists (select /*+ semi_join_rewrite(), no_decorrelate() */ * from t1 where t1.a=t3.a) from t3",
        "Plan": [
          "HashJoin 10000.00 root  left outer semi join, equal:[eq(test.t3.a, test.t1.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1",
          "1"
        ],
        "Warning": [
          "Warning 1815 NO_DECORRELATE() and SEMI_JOIN_REWRITE() are in conflict. Both will be ineffective."
        ]
      },
      {
        "SQL": "select t1.a from t1 where t1.a in (select t2.b from t2 where t2.a = t1.b)",
        "Plan": [
          "HashJoin 7984.01 root  semi join, equal:[eq(test.t1.b, test.t2.a) eq(test.t1.a, test.t2.b)]",
          "├─TableReader(Build) 9990.00 root  data:Selection",
          "│ └─Selection 9990.00 cop[tikv]  not(isnull(test.t2.b))",
          "│   └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 9980.01 root  data:Selection",
          "  └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
          "    └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1"
        ],
        "Warning": null
      },
      {
        "SQL": "select t1.a from t1 where t1.a in (select /*+ no_decorrelate() */ t2.b from t2 where t2.a = t1.b)",
        "Plan": [
          "Projection 9990.00 root  test.t1.a",
          "└─Apply 9990.00 root  semi join, equal:[eq(test.t1.a, test.t2.b)]",
          "  ├─TableReader(Build) 9990.00 root  data:Selection",
          "  │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t1.a))",
          "  │   └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "  └─TableReader(Probe) 99800.10 root  data:Selection",
          "    └─Selection 99800.10 cop[tikv]  not(isnull(test.t2.b))",
          "      └─TableRangeScan 9990.00 cop[tikv] table:t2 range: decided by [eq(test.t2.a, test.t1.b)], keep order:false, stats:pseudo"
        ],
        "Result": [
          "1"
        ],
        "Warning": null
      },
      {
        "SQL": "select t1.a from t1 where t1.a = any (select t2.b from t2 where t2.a = t1.b)",
        "Plan": [
          "Projection 8000.00 root  test.t1.a",
          "└─Selection 8000.00 root  Column#6",
          "  └─HashJoin 10000.00 root  left outer semi join, equal:[eq(test.t1.b, test.t2.a)], other cond:eq(test.t1.a, test.t2.b)",
          "    ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "    │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "    └─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "      └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1"
        ],
        "Warning": null
      },
      {
        "SQL": "select t1.a from t1 where t1.a = any (select /*+ no_decorrelate() */ t2.b from t2 where t2.a = t1.b)",
        "Plan": [
          "Projection 8000.00 root  test.t1.a",
          "└─Selection 8000.00 root  Column#6",
          "  └─Apply 10000.00 root  CARTESIAN left outer semi join, other cond:eq(test.t1.a, test.t2.b)",
          "    ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "    │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "    └─TableReader(Probe) 10000.00 root  data:TableRangeScan",
          "      └─TableRangeScan 10000.00 cop[tikv] table:t2 range: decided by [eq(test.t2.a, test.t1.b)], keep order:false, stats:pseudo"
        ],
        "Result": [
          "1"
        ],
        "Warning": null
      },
      {
        "SQL": "select t1.a, t1.a != any (select t2.b from t2 where t2.a = t1.b) from t1",
        "Plan": [
          "Projection 10000.00 root  test.t1.a, and(or(or(gt(Column#9, 1), ne(test.t1.a, Column#8)), if(ne(Column#10, 0), <nil>, 0)), and(ne(Column#11, 0), if(isnull(test.t1.a), <nil>, 1)))->Column#12",
          "└─Apply 10000.00 root  CARTESIAN inner join",
          "  ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "  │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "  └─StreamAgg(Probe) 10000.00 root  funcs:max(Column#14)->Column#8, funcs:count(distinct Column#15)->Column#9, funcs:sum(Column#16)->Column#10, funcs:count(1)->Column#11",
          "    └─Projection 10000.00 root  test.t2.b, test.t2.b, cast(isnull(test.t2.b), decimal(20,0) BINARY)->Column#16",
          "      └─TableReader 10000.00 root  data:TableRangeScan",
          "        └─TableRangeScan 10000.00 cop[tikv] table:t2 range: decided by [eq(test.t2.a, test.t1.b)], keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 0",
          "2 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select t1.a, t1.a != any (select /*+ no_decorrelate() */ t2.b from t2 where t2.a = t1.b) from t1",
        "Plan": [
          "Projection 10000.00 root  test.t1.a, and(or(or(gt(Column#9, 1), ne(test.t1.a, Column#8)), if(ne(Column#10, 0), <nil>, 0)), and(ne(Column#11, 0), if(isnull(test.t1.a), <nil>, 1)))->Column#12",
          "└─Apply 10000.00 root  CARTESIAN inner join",
          "  ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "  │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "  └─StreamAgg(Probe) 10000.00 root  funcs:max(Column#14)->Column#8, funcs:count(distinct Column#15)->Column#9, funcs:sum(Column#16)->Column#10, funcs:count(1)->Column#11",
          "    └─Projection 10000.00 root  test.t2.b, test.t2.b, cast(isnull(test.t2.b), decimal(20,0) BINARY)->Column#16",
          "      └─TableReader 10000.00 root  data:TableRangeScan",
          "        └─TableRangeScan 10000.00 cop[tikv] table:t2 range: decided by [eq(test.t2.a, test.t1.b)], keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 0",
          "2 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select t1.a, t1.a > all (select t2.b from t2 where t2.a = t1.b) from t1",
        "Plan": [
          "Projection 10000.00 root  test.t1.a, or(and(gt(test.t1.a, Column#8), if(ne(Column#9, 0), <nil>, 1)), or(eq(Column#10, 0), if(isnull(test.t1.a), <nil>, 0)))->Column#11",
          "└─Apply 10000.00 root  CARTESIAN inner join",
          "  ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "  │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "  └─StreamAgg(Probe) 10000.00 root  funcs:max(Column#19)->Column#8, funcs:sum(Column#20)->Column#9, funcs:count(1)->Column#10",
          "    └─Projection 10000.00 root  test.t2.b, cast(isnull(test.t2.b), decimal(20,0) BINARY)->Column#20",
          "      └─TableReader 10000.00 root  data:TableRangeScan",
          "        └─TableRangeScan 10000.00 cop[tikv] table:t2 range: decided by [eq(test.t2.a, test.t1.b)], keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 0",
          "2 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select t1.a, t1.a > all (select /*+ no_decorrelate() */ t2.b from t2 where t2.a = t1.b) from t1",
        "Plan": [
          "Projection 10000.00 root  test.t1.a, or(and(gt(test.t1.a, Column#8), if(ne(Column#9, 0), <nil>, 1)), or(eq(Column#10, 0), if(isnull(test.t1.a), <nil>, 0)))->Column#11",
          "└─Apply 10000.00 root  CARTESIAN inner join",
          "  ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "  │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "  └─StreamAgg(Probe) 10000.00 root  funcs:max(Column#19)->Column#8, funcs:sum(Column#20)->Column#9, funcs:count(1)->Column#10",
          "    └─Projection 10000.00 root  test.t2.b, cast(isnull(test.t2.b), decimal(20,0) BINARY)->Column#20",
          "      └─TableReader 10000.00 root  data:TableRangeScan",
          "        └─TableRangeScan 10000.00 cop[tikv] table:t2 range: decided by [eq(test.t2.a, test.t1.b)], keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 0",
          "2 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select t1.a, (select t2.b from t2 where t2.a = t1.b) from t1",
        "Plan": [
          "HashJoin 12500.00 root  left outer join, equal:[eq(test.t1.b, test.t2.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select t1.a, (select /*+ no_decorrelate() */ t2.b from t2 where t2.a = t1.b) from t1",
        "Plan": [
          "Projection 10000.00 root  test.t1.a, test.t2.b",
          "└─Apply 10000.00 root  CARTESIAN left outer join",
          "  ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "  │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "  └─MaxOneRow(Probe) 10000.00 root  ",
          "    └─TableReader 2000.00 root  data:TableRangeScan",
          "      └─TableRangeScan 2000.00 cop[tikv] table:t2 range: decided by [eq(test.t2.a, test.t1.b)], keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 1",
          "2 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select t1.a, t1.b not in (select t3.b from t3) from t1",
        "Plan": [
          "HashJoin 10000.00 root  CARTESIAN anti left outer semi join, other cond:eq(test.t1.b, test.t3.b)",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 0",
          "2 1"
        ],
        "Warning": null
      },
      {
        "SQL": "select t1.a, t1.b not in (select /*+ no_decorrelate() */ t3.b from t3) from t1",
        "Plan": [
          "HashJoin 10000.00 root  CARTESIAN anti left outer semi join, other cond:eq(test.t1.b, test.t3.b)",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 0",
          "2 1"
        ],
        "Warning": [
          "Warning 1815 NO_DECORRELATE() is inapplicable because there are no correlated columns."
        ]
      },
      {
        "SQL": "select exists (select t3.b from t3 where t3.a = t1.b limit 2) from t1",
        "Plan": [
          "HashJoin 10000.00 root  left outer semi join, equal:[eq(test.t1.b, test.t3.a)]",
          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "│ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1",
          "1"
        ],
        "Warning": null
      },
      {
        "SQL": "select exists (select /*+ no_decorrelate() */ t3.b from t3 where t3.a = t1.b limit 2) from t1",
        "Plan": [
          "Projection 10000.00 root  Column#10",
          "└─Apply 10000.00 root  CARTESIAN left outer semi join",
          "  ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "  │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "  └─Limit(Probe) 20000.00 root  offset:0, count:2",
          "    └─TableReader 20000.00 root  data:Limit",
          "      └─Limit 20000.00 cop[tikv]  offset:0, count:2",
          "        └─Selection 20000.00 cop[tikv]  eq(test.t3.a, test.t1.b)",
          "          └─TableFullScan 20000000.00 cop[tikv] table:t3 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1",
          "1"
        ],
        "Warning": null
      },
      {
        "SQL": "select t1.a, (select sum(t1.a) from t2 where t2.a = 10) from t1",
        "Plan": [
          "Projection 1.00 root  test.t1.a, Column#6",
          "└─HashJoin 1.00 root  CARTESIAN left outer join",
          "  ├─Point_Get(Build) 1.00 root table:t2 handle:10",
          "  └─HashAgg(Probe) 1.00 root  funcs:sum(Column#13)->Column#6, funcs:firstrow(Column#14)->test.t1.a",
          "    └─TableReader 1.00 root  data:HashAgg",
          "      └─HashAgg 1.00 cop[tikv]  funcs:sum(test.t1.a)->Column#13, funcs:firstrow(test.t1.a)->Column#14",
          "        └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "1 3"
        ],
        "Warning": null
      },
      {
        "SQL": "select t1.a, (select /*+ no_decorrelate() */ sum(t1.a) from t2 where t2.a = 10) from t1",
        "Plan": [
          "Projection 1.00 root  test.t1.a, Column#9",
          "└─Apply 1.00 root  CARTESIAN left outer join",
          "  ├─HashAgg(Build) 1.00 root  funcs:sum(Column#14)->Column#6, funcs:firstrow(Column#15)->test.t1.a",
          "  │ └─Projection 10000.00 root  cast(test.t1.a, decimal(10,0) BINARY)->Column#14, test.t1.a",
          "  │   └─TableReader 10000.00 root  data:TableFullScan",
          "  │     └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "  └─MaxOneRow(Probe) 1.00 root  ",
          "    └─Projection 1.00 root  Column#6",
          "      └─Point_Get 1.00 root table:t2 handle:10"
        ],
        "Result": [
          "1 <nil>"
        ],
        "Warning": null
      },
      {
        "SQL": "select (select count(t3.a) from t3 where t3.b = t1.b) from t1;",
        "Plan": [
          "Projection 10000.00 root  ifnull(Column#10, 0)->Column#10",
          "└─HashJoin 10000.00 root  left outer join, equal:[eq(test.t1.b, test.t3.b)]",
          "  ├─HashAgg(Build) 7992.00 root  group by:test.t3.b, funcs:count(Column#11)->Column#10, funcs:firstrow(test.t3.b)->test.t3.b",
          "  │ └─TableReader 7992.00 root  data:HashAgg",
          "  │   └─HashAgg 7992.00 cop[tikv]  group by:test.t3.b, funcs:count(test.t3.a)->Column#11",
          "  │     └─Selection 9990.00 cop[tikv]  not(isnull(test.t3.b))",
          "  │       └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
          "  └─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "    └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Result": [
          "0",
          "2"
        ],
        "Warning": null
      },
      {
        "SQL": "select (select /*+ no_decorrelate() */ count(t3.a) from t3 where t3.b = t1.b) from t1;",
        "Plan": [
          "Projection 10000.00 root  Column#10",
          "└─Apply 10000.00 root  CARTESIAN left outer join",
          "  ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "  │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
          "  └─MaxOneRow(Probe) 10000.00 root  ",
          "    └─StreamAgg 10000.00 root  funcs:count(Column#12)->Column#10",
          "      └─TableReader 10000.00 root  data:StreamAgg",
          "        └─StreamAgg 10000.00 cop[tikv]  funcs:count(test.t3.a)->Column#12",
          "          └─Selection 100000.00 cop[tikv]  eq(test.t3.b, test.t1.b)",
          "            └─TableFullScan 100000000.00 cop[tikv] table:t3 keep order:false, stats:pseudo"
        ],
        "Result": [
          "0",
          "2"
        ],
        "Warning": null
      },
      {
        "SQL": "SELECT ta.NAME,(SELECT sum(tb.CODE) FROM tb WHERE ta.id = tb.id) tb_sum_code FROM ta WHERE ta.NAME LIKE 'chad999%'",
        "Plan": [
          "HashJoin 250.00 root  left outer join, equal:[eq(test.ta.id, test.tb.id)]",
          "├─TableReader(Build) 250.00 root  data:Selection",
          "│ └─Selection 250.00 cop[tikv]  like(test.ta.name, \"chad999%\", 92)",
          "│   └─TableFullScan 10000.00 cop[tikv] table:ta keep order:false, stats:pseudo",
          "└─HashAgg(Probe) 7992.00 root  group by:test.tb.id, funcs:sum(Column#19)->Column#13, funcs:firstrow(test.tb.id)->test.tb.id",
          "  └─TableReader 7992.00 root  data:HashAgg",
          "    └─HashAgg 7992.00 cop[tikv]  group by:test.tb.id, funcs:sum(test.tb.code)->Column#19",
          "      └─Selection 9990.00 cop[tikv]  not(isnull(test.tb.id))",
          "        └─TableFullScan 10000.00 cop[tikv] table:tb keep order:false, stats:pseudo"
        ],
        "Result": null,
        "Warning": null
      },
      {
        "SQL": "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%'",
        "Plan": [
          "Projection 250.00 root  test.ta.name, Column#13",
          "└─Apply 250.00 root  CARTESIAN left outer join",
          "  ├─TableReader(Build) 250.00 root  data:Selection",
          "  │ └─Selection 250.00 cop[tikv]  like(test.ta.name, \"chad999%\", 92)",
          "  │   └─TableFullScan 10000.00 cop[tikv] table:ta keep order:false, stats:pseudo",
          "  └─MaxOneRow(Probe) 250.00 root  ",
          "    └─StreamAgg 250.00 root  funcs:sum(Column#21)->Column#13",
          "      └─Projection 2500.00 root  cast(test.tb.code, decimal(10,0) BINARY)->Column#21",
          "        └─IndexLookUp 2500.00 root  ",
          "          ├─IndexRangeScan(Build) 2500.00 cop[tikv] table:tb, index:idx_tb_id(id) range: decided by [eq(test.ta.id, test.tb.id)], keep order:false, stats:pseudo",
          "          └─TableRowIDScan(Probe) 2500.00 cop[tikv] table:tb keep order:false, stats:pseudo"
        ],
        "Result": null,
        "Warning": null
      },
      {
        "SQL": "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%'",
        "Plan": [
          "HashJoin 250.00 root  left outer join, equal:[eq(test.ta.id, test.tb.id)]",
          "├─TableReader(Build) 250.00 root  data:Selection",
          "│ └─Selection 250.00 cop[tikv]  like(test.ta.name, \"chad999%\", 92)",
          "│   └─TableFullScan 10000.00 cop[tikv] table:ta keep order:false, stats:pseudo",
          "└─HashAgg(Probe) 6387.21 root  group by:Column#39, funcs:sum(Column#37)->Column#18, funcs:firstrow(Column#38)->test.tb.id",
          "  └─Projection 7984.01 root  cast(test.tb.code, decimal(10,0) BINARY)->Column#37, test.tb.id, test.tb.id",
          "    └─HashJoin 7984.01 root  semi join, equal:[eq(test.tb.name, test.tc.name)]",
          "      ├─TableReader(Build) 7992.00 root  data:Selection",
          "      │ └─Selection 7992.00 cop[tikv]  like(cast(test.tc.code, var_string(20)), \"999%\", 92), not(isnull(test.tc.name))",
          "      │   └─TableFullScan 10000.00 cop[tikv] table:tc keep order:false, stats:pseudo",
          "      └─TableReader(Probe) 9980.01 root  data:Selection",
          "        └─Selection 9980.01 cop[tikv]  not(isnull(test.tb.id)), not(isnull(test.tb.name))",
          "          └─TableFullScan 10000.00 cop[tikv] table:tb keep order:false, stats:pseudo"
        ],
        "Result": null,
        "Warning": null
      },
      {
        "SQL": "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%'",
        "Plan": [
          "Projection 250.00 root  test.ta.name, Column#18",
          "└─Apply 250.00 root  CARTESIAN left outer join",
          "  ├─TableReader(Build) 250.00 root  data:Selection",
          "  │ └─Selection 250.00 cop[tikv]  like(test.ta.name, \"chad999%\", 92)",
          "  │   └─TableFullScan 10000.00 cop[tikv] table:ta keep order:false, stats:pseudo",
          "  └─MaxOneRow(Probe) 250.00 root  ",
          "    └─StreamAgg 250.00 root  funcs:sum(Column#33)->Column#18",
          "      └─Projection 1998.00 root  cast(test.tb.code, decimal(10,0) BINARY)->Column#33",
          "        └─IndexHashJoin 1998.00 root  semi join, inner:IndexLookUp, outer key:test.tb.name, inner key:test.tc.name, equal cond:eq(test.tb.name, test.tc.name)",
          "          ├─IndexLookUp(Build) 2497.50 root  ",
          "          │ ├─IndexRangeScan(Build) 2500.00 cop[tikv] table:tb, index:idx_tb_id(id) range: decided by [eq(test.ta.id, test.tb.id)], keep order:false, stats:pseudo",
          "          │ └─Selection(Probe) 2497.50 cop[tikv]  not(isnull(test.tb.name))",
          "          │   └─TableRowIDScan 2500.00 cop[tikv] table:tb keep order:false, stats:pseudo",
          "          └─IndexLookUp(Probe) 3121.87 root  ",
          "            ├─Selection(Build) 3902.34 cop[tikv]  not(isnull(test.tc.name))",
          "            │ └─IndexRangeScan 3906.25 cop[tikv] table:tc, index:idx_tc_name(name) range: decided by [eq(test.tc.name, test.tb.name)], keep order:false, stats:pseudo",
          "            └─Selection(Probe) 3121.87 cop[tikv]  like(cast(test.tc.code, var_string(20)), \"999%\", 92)",
          "              └─TableRowIDScan 3902.34 cop[tikv] table:tc keep order:false, stats:pseudo"
        ],
        "Result": null,
        "Warning": null
      },
      {
        "SQL": "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%'",
        "Plan": [
          "HashJoin 250.00 root  left outer join, equal:[eq(test.ta.id, test.tb.id)]",
          "├─TableReader(Build) 250.00 root  data:Selection",
          "│ └─Selection 250.00 cop[tikv]  like(test.ta.name, \"chad999%\", 92)",
          "│   └─TableFullScan 10000.00 cop[tikv] table:ta keep order:false, stats:pseudo",
          "└─HashAgg(Probe) 7992.00 root  group by:Column#28, funcs:sum(Column#26)->Column#18, funcs:firstrow(Column#27)->test.tb.id",
          "  └─Projection 9990.00 root  cast(test.tb.code, decimal(10,0) BINARY)->Column#26, test.tb.id, test.tb.id",
          "    └─Apply 9990.00 root  CARTESIAN semi join",
          "      ├─TableReader(Build) 9990.00 root  data:Selection",
          "      │ └─Selection 9990.00 cop[tikv]  not(isnull(test.tb.id))",
          "      │   └─TableFullScan 10000.00 cop[tikv] table:tb keep order:false, stats:pseudo",
          "      └─IndexLookUp(Probe) 79920.00 root  ",
          "        ├─IndexRangeScan(Build) 99900.00 cop[tikv] table:tc, index:idx_tc_name(name) range: decided by [eq(test.tb.name, test.tc.name)], keep order:false, stats:pseudo",
          "        └─Selection(Probe) 79920.00 cop[tikv]  like(cast(test.tc.code, var_string(20)), \"999%\", 92)",
          "          └─TableRowIDScan 99900.00 cop[tikv] table:tc keep order:false, stats:pseudo"
        ],
        "Result": null,
        "Warning": null
      },
      {
        "SQL": "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%'",
        "Plan": [
          "Projection 250.00 root  test.ta.name, Column#18",
          "└─Apply 250.00 root  CARTESIAN left outer join",
          "  ├─TableReader(Build) 250.00 root  data:Selection",
          "  │ └─Selection 250.00 cop[tikv]  like(test.ta.name, \"chad999%\", 92)",
          "  │   └─TableFullScan 10000.00 cop[tikv] table:ta keep order:false, stats:pseudo",
          "  └─MaxOneRow(Probe) 250.00 root  ",
          "    └─StreamAgg 250.00 root  funcs:sum(Column#22)->Column#18",
          "      └─Projection 2500.00 root  cast(test.tb.code, decimal(10,0) BINARY)->Column#22",
          "        └─Apply 2500.00 root  CARTESIAN semi join",
          "          ├─IndexLookUp(Build) 2500.00 root  ",
          "          │ ├─IndexRangeScan(Build) 2500.00 cop[tikv] table:tb, index:idx_tb_id(id) range: decided by [eq(test.ta.id, test.tb.id)], keep order:false, stats:pseudo",
          "          │ └─TableRowIDScan(Probe) 2500.00 cop[tikv] table:tb keep order:false, stats:pseudo",
          "          └─IndexLookUp(Probe) 20000.00 root  ",
          "            ├─IndexRangeScan(Build) 25000.00 cop[tikv] table:tc, index:idx_tc_name(name) range: decided by [eq(test.tb.name, test.tc.name)], keep order:false, stats:pseudo",
          "            └─Selection(Probe) 20000.00 cop[tikv]  like(cast(test.tc.code, var_string(20)), \"999%\", 92)",
          "              └─TableRowIDScan 25000.00 cop[tikv] table:tc keep order:false, stats:pseudo"
        ],
        "Result": null,
        "Warning": null
      },
      {
        "SQL": "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",
        "Plan": [
          "Projection 9.99 root  test.ta.id, split->Column#10",
          "└─HashJoin 9.99 root  inner join, equal:[eq(test.ta.id, test.tb.id)]",
          "  ├─IndexLookUp(Build) 9.99 root  ",
          "  │ ├─IndexRangeScan(Build) 10.00 cop[tikv] table:ta, index:idx_ta_name(name) range:[\"chad999\",\"chad999\"], keep order:false, stats:pseudo",
          "  │ └─Selection(Probe) 9.99 cop[tikv]  not(isnull(test.ta.id))",
          "  │   └─TableRowIDScan 10.00 cop[tikv] table:ta keep order:false, stats:pseudo",
          "  └─Selection(Probe) 6393.60 root  gt(Column#9, 900)",
          "    └─HashAgg 7992.00 root  group by:test.tb.id, funcs:max(Column#19)->Column#9, funcs:firstrow(test.tb.id)->test.tb.id",
          "      └─TableReader 7992.00 root  data:HashAgg",
          "        └─HashAgg 7992.00 cop[tikv]  group by:test.tb.id, funcs:max(test.tb.code)->Column#19",
          "          └─Selection 9990.00 cop[tikv]  not(isnull(test.tb.id))",
          "            └─TableFullScan 10000.00 cop[tikv] table:tb keep order:false, stats:pseudo"
        ],
        "Result": null,
        "Warning": null
      },
      {
        "SQL": "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",
        "Plan": [
          "Projection 10.00 root  test.ta.id, split->Column#10",
          "└─Apply 10.00 root  CARTESIAN inner join",
          "  ├─IndexLookUp(Build) 10.00 root  ",
          "  │ ├─IndexRangeScan(Build) 10.00 cop[tikv] table:ta, index:idx_ta_name(name) range:[\"chad999\",\"chad999\"], keep order:false, stats:pseudo",
          "  │ └─TableRowIDScan(Probe) 10.00 cop[tikv] table:ta keep order:false, stats:pseudo",
          "  └─Selection(Probe) 8.00 root  gt(Column#9, 900)",
          "    └─MaxOneRow 10.00 root  ",
          "      └─StreamAgg 10.00 root  funcs:max(test.tb.code)->Column#9",
          "        └─TopN 10.00 root  test.tb.code:desc, offset:0, count:1",
          "          └─IndexLookUp 10.00 root  ",
          "            ├─IndexRangeScan(Build) 100.00 cop[tikv] table:tb, index:idx_tb_id(id) range: decided by [eq(test.ta.id, test.tb.id)], keep order:false, stats:pseudo",
          "            └─TopN(Probe) 10.00 cop[tikv]  test.tb.code:desc, offset:0, count:1",
          "              └─Selection 99.90 cop[tikv]  not(isnull(test.tb.code))",
          "                └─TableRowIDScan 100.00 cop[tikv] table:tb keep order:false, stats:pseudo"
        ],
        "Result": null,
        "Warning": null
      },
      {
        "SQL": "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",
        "Plan": [
          "HashJoin 159.84 root  inner join, equal:[eq(test.ta.id, test.td.id)]",
          "├─Selection(Build) 159.84 root  gt(Column#19, 100)",
          "│ └─HashAgg 199.80 root  group by:test.td.id, funcs:max(Column#32)->Column#19, funcs:firstrow(test.td.id)->test.td.id",
          "│   └─TableReader 199.80 root  data:HashAgg",
          "│     └─HashAgg 199.80 cop[tikv]  group by:test.td.id, funcs:max(test.td.id)->Column#32",
          "│       └─Selection 249.75 cop[tikv]  like(test.td.name, \"chad999%\", 92), not(isnull(test.td.id))",
          "│         └─TableFullScan 10000.00 cop[tikv] table:td keep order:false, stats:pseudo",
          "└─HashJoin(Probe) 200.00 root  inner join, equal:[eq(test.ta.name, test.tc.name)]",
          "  ├─Selection(Build) 160.00 root  gt(Column#14, 100)",
          "  │ └─HashAgg 200.00 root  group by:test.tc.name, funcs:max(Column#24)->Column#14, funcs:firstrow(test.tc.name)->test.tc.name",
          "  │   └─TableReader 200.00 root  data:HashAgg",
          "  │     └─HashAgg 200.00 cop[tikv]  group by:test.tc.name, funcs:max(test.tc.id)->Column#24",
          "  │       └─Selection 250.00 cop[tikv]  like(test.tc.name, \"chad99%\", 92), not(isnull(test.tc.name))",
          "  │         └─TableFullScan 10000.00 cop[tikv] table:tc keep order:false, stats:pseudo",
          "  └─HashJoin(Probe) 7976.02 root  semi join, equal:[eq(test.ta.code, test.tb.code)]",
          "    ├─TableReader(Build) 249.75 root  data:Selection",
          "    │ └─Selection 249.75 cop[tikv]  like(test.tb.name, \"chad9%\", 92), not(isnull(test.tb.code))",
          "    │   └─TableFullScan 10000.00 cop[tikv] table:tb keep order:false, stats:pseudo",
          "    └─TableReader(Probe) 9970.03 root  data:Selection",
          "      └─Selection 9970.03 cop[tikv]  not(isnull(test.ta.code)), not(isnull(test.ta.id)), not(isnull(test.ta.name))",
          "        └─TableFullScan 10000.00 cop[tikv] table:ta keep order:false, stats:pseudo"
        ],
        "Result": null,
        "Warning": null
      },
      {
        "SQL": "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",
        "Plan": [
          "Projection 249.75 root  test.ta.name",
          "└─Apply 249.75 root  CARTESIAN inner join",
          "  ├─Apply(Build) 249.75 root  CARTESIAN inner join",
          "  │ ├─IndexHashJoin(Build) 249.75 root  inner join, inner:IndexLookUp, outer key:test.tb.code, inner key:test.ta.code, equal cond:eq(test.tb.code, test.ta.code)",
          "  │ │ ├─HashAgg(Build) 199.80 root  group by:test.tb.code, funcs:firstrow(test.tb.code)->test.tb.code",
          "  │ │ │ └─TableReader 249.75 root  data:Selection",
          "  │ │ │   └─Selection 249.75 cop[tikv]  like(test.tb.name, \"chad9%\", 92), not(isnull(test.tb.code))",
          "  │ │ │     └─TableFullScan 10000.00 cop[tikv] table:tb keep order:false, stats:pseudo",
          "  │ │ └─IndexLookUp(Probe) 249.75 root  ",
          "  │ │   ├─Selection(Build) 249.75 cop[tikv]  not(isnull(test.ta.code))",
          "  │ │   │ └─IndexRangeScan 250.00 cop[tikv] table:ta, index:idx_ta_code(code) range: decided by [eq(test.ta.code, test.tb.code)], keep order:false, stats:pseudo",
          "  │ │   └─TableRowIDScan(Probe) 249.75 cop[tikv] table:ta keep order:false, stats:pseudo",
          "  │ └─Selection(Probe) 199.80 root  gt(Column#14, 100)",
          "  │   └─MaxOneRow 249.75 root  ",
          "  │     └─StreamAgg 249.75 root  funcs:max(test.tc.id)->Column#14",
          "  │       └─TopN 62.38 root  test.tc.id:desc, offset:0, count:1",
          "  │         └─IndexLookUp 62.38 root  ",
          "  │           ├─Selection(Build) 62.44 cop[tikv]  eq(test.ta.name, test.tc.name)",
          "  │           │ └─IndexRangeScan 62437.50 cop[tikv] table:tc, index:idx_tc_name(name) range:[\"chad99\",\"chad9:\"), keep order:false, stats:pseudo",
          "  │           └─TopN(Probe) 62.38 cop[tikv]  test.tc.id:desc, offset:0, count:1",
          "  │             └─Selection 62.38 cop[tikv]  not(isnull(test.tc.id))",
          "  │               └─TableRowIDScan 62.44 cop[tikv] table:tc keep order:false, stats:pseudo",
          "  └─Selection(Probe) 199.80 root  gt(Column#19, 100)",
          "    └─MaxOneRow 249.75 root  ",
          "      └─StreamAgg 249.75 root  funcs:max(test.td.id)->Column#19",
          "        └─Limit 62.38 root  offset:0, count:1",
          "          └─Projection 62.38 root  test.td.id, test.td.name",
          "            └─IndexLookUp 62.38 root  ",
          "              ├─Selection(Build) 2495.00 cop[tikv]  eq(test.ta.id, test.td.id)",
          "              │ └─IndexFullScan 2495002.50 cop[tikv] table:td, index:idx_tc_id(id) keep order:true, desc, stats:pseudo",
          "              └─Selection(Probe) 62.38 cop[tikv]  like(test.td.name, \"chad999%\", 92)",
          "                └─TableRowIDScan 2495.00 cop[tikv] table:td keep order:false, stats:pseudo"
        ],
        "Result": null,
        "Warning": null
      },
      {
        "SQL": "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",
        "Plan": [
          "Projection 10000.00 root  test.ta.name",
          "└─Apply 10000.00 root  CARTESIAN inner join",
          "  ├─Apply(Build) 10000.00 root  CARTESIAN inner join",
          "  │ ├─Apply(Build) 10000.00 root  CARTESIAN semi join",
          "  │ │ ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "  │ │ │ └─TableFullScan 10000.00 cop[tikv] table:ta keep order:false, stats:pseudo",
          "  │ │ └─TableReader(Probe) 2500.00 root  data:Selection",
          "  │ │   └─Selection 2500.00 cop[tikv]  eq(test.ta.code, test.tb.code), like(test.tb.name, \"chad9%\", 92)",
          "  │ │     └─TableFullScan 100000000.00 cop[tikv] table:tb keep order:false, stats:pseudo",
          "  │ └─Selection(Probe) 8000.00 root  gt(Column#14, 100)",
          "  │   └─MaxOneRow 10000.00 root  ",
          "  │     └─StreamAgg 10000.00 root  funcs:max(test.tc.id)->Column#14",
          "  │       └─TopN 2497.50 root  test.tc.id:desc, offset:0, count:1",
          "  │         └─IndexLookUp 2497.50 root  ",
          "  │           ├─Selection(Build) 2500.00 cop[tikv]  eq(test.ta.name, test.tc.name)",
          "  │           │ └─IndexRangeScan 2500000.00 cop[tikv] table:tc, index:idx_tc_name(name) range:[\"chad99\",\"chad9:\"), keep order:false, stats:pseudo",
          "  │           └─TopN(Probe) 2497.50 cop[tikv]  test.tc.id:desc, offset:0, count:1",
          "  │             └─Selection 2497.50 cop[tikv]  not(isnull(test.tc.id))",
          "  │               └─TableRowIDScan 2500.00 cop[tikv] table:tc keep order:false, stats:pseudo",
          "  └─Selection(Probe) 8000.00 root  gt(Column#19, 100)",
          "    └─MaxOneRow 10000.00 root  ",
          "      └─StreamAgg 10000.00 root  funcs:max(test.td.id)->Column#19",
          "        └─Limit 2497.50 root  offset:0, count:1",
          "          └─Projection 2497.50 root  test.td.id, test.td.name",
          "            └─IndexLookUp 2497.50 root  ",
          "              ├─Selection(Build) 99900.00 cop[tikv]  eq(test.ta.id, test.td.id)",
          "              │ └─IndexFullScan 99900000.00 cop[tikv] table:td, index:idx_tc_id(id) keep order:true, desc, stats:pseudo",
          "              └─Selection(Probe) 2497.50 cop[tikv]  like(test.td.name, \"chad999%\", 92)",
          "                └─TableRowIDScan 99900.00 cop[tikv] table:td keep order:false, stats:pseudo"
        ],
        "Result": null,
        "Warning": null
      }
    ]
  },
  {
    "Name": "TestCountStarForTikv",
    "Cases": [
      {
        "SQL": "select count(*) from t",
        "Plan": [
          "StreamAgg 1.00 root  funcs:count(Column#12)->Column#10",
          "└─TableReader 1.00 root  data:StreamAgg",
          "  └─StreamAgg 1.00 cop[tikv]  funcs:count(1)->Column#12",
          "    └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "select count(1), count(3.1415), count(0), count(null) from t -- shouldn't be rewritten",
        "Plan": [
          "StreamAgg 1.00 root  funcs:count(Column#18)->Column#10, funcs:count(Column#19)->Column#11, funcs:count(Column#20)->Column#12, funcs:count(Column#21)->Column#13",
          "└─TableReader 1.00 root  data:StreamAgg",
          "  └─StreamAgg 1.00 cop[tikv]  funcs:count(1)->Column#18, funcs:count(3.1415)->Column#19, funcs:count(0)->Column#20, funcs:count(NULL)->Column#21",
          "    └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "select count(*) from t where a=1",
        "Plan": [
          "StreamAgg 1.00 root  funcs:count(Column#12)->Column#10",
          "└─TableReader 1.00 root  data:StreamAgg",
          "  └─StreamAgg 1.00 cop[tikv]  funcs:count(1)->Column#12",
          "    └─Selection 10.00 cop[tikv]  eq(test.t.a, 1)",
          "      └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "select count(*) from t_pick_row_id",
        "Plan": [
          "StreamAgg 1.00 root  funcs:count(Column#5)->Column#3",
          "└─TableReader 1.00 root  data:StreamAgg",
          "  └─StreamAgg 1.00 cop[tikv]  funcs:count(1)->Column#5",
          "    └─TableFullScan 10000.00 cop[tikv] table:t_pick_row_id keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "select t.b, t.c from (select count(*) as c from t) a, t where a.c=t.a -- shouldn't be rewritten",
        "Plan": [
          "HashJoin 1.25 root  inner join, equal:[eq(test.t.a, Column#10)]",
          "├─StreamAgg(Build) 1.00 root  funcs:count(Column#21)->Column#10",
          "│ └─TableReader 1.00 root  data:StreamAgg",
          "│   └─StreamAgg 1.00 cop[tikv]  funcs:count(1)->Column#21",
          "│     └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "select * from t out1 where out1.a > (select count(*) from t inn where inn.a = out1.b) -- shouldn't be rewritten",
        "Plan": [
          "Projection 10000.00 root  test.t.a, test.t.b, test.t.c, test.t.d, test.t.e, test.t.f, test.t.g, test.t.h",
          "└─Apply 10000.00 root  CARTESIAN inner join, other cond:gt(test.t.a, Column#19)",
          "  ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "  │ └─TableFullScan 10000.00 cop[tikv] table:out1 keep order:false, stats:pseudo",
          "  └─StreamAgg(Probe) 10000.00 root  funcs:count(Column#21)->Column#19",
          "    └─TableReader 10000.00 root  data:StreamAgg",
          "      └─StreamAgg 10000.00 cop[tikv]  funcs:count(1)->Column#21",
          "        └─Selection 80000000.00 cop[tikv]  eq(cast(test.t.a, double BINARY), cast(test.t.b, double BINARY))",
          "          └─TableFullScan 100000000.00 cop[tikv] table:inn keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "select count(*) from t t1, t t2 where t1.a=t2.e -- shouldn't be rewritten",
        "Plan": [
          "HashAgg 1.00 root  funcs:count(1)->Column#19",
          "└─HashJoin 12500.00 root  inner join, equal:[eq(test.t.a, test.t.e)]",
          "  ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "  │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
          "  └─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "    └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "select count(distinct 1) from t -- shouldn't be rewritten",
        "Plan": [
          "StreamAgg 1.00 root  funcs:count(distinct 1)->Column#10",
          "└─TableReader 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "select count(1), count(a), count(b) from t -- shouldn't be rewritten",
        "Plan": [
          "StreamAgg 1.00 root  funcs:count(Column#16)->Column#10, funcs:count(Column#17)->Column#11, funcs:count(Column#18)->Column#12",
          "└─TableReader 1.00 root  data:StreamAgg",
          "  └─StreamAgg 1.00 cop[tikv]  funcs:count(1)->Column#16, funcs:count(test.t.a)->Column#17, funcs:count(test.t.b)->Column#18",
          "    └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "select a, count(*) from t group by a -- shouldn't be rewritten",
        "Plan": [
          "Projection 8000.00 root  test.t.a, Column#10",
          "└─HashAgg 8000.00 root  group by:test.t.a, funcs:count(1)->Column#10, funcs:firstrow(test.t.a)->test.t.a",
          "  └─TableReader 10000.00 root  data:TableFullScan",
          "    └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "select sum(a) from t -- sum shouldn't be rewritten",
        "Plan": [
          "StreamAgg 1.00 root  funcs:sum(Column#12)->Column#10",
          "└─TableReader 1.00 root  data:StreamAgg",
          "  └─StreamAgg 1.00 cop[tikv]  funcs:sum(test.t.a)->Column#12",
          "    └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
        ],
        "Warning": null
      }
    ]
  },
  {
    "Name": "TestCountStarForTiFlash",
    "Cases": [
      {
        "SQL": "select count(*) from t",
        "Plan": [
          "HashAgg 1.00 root  funcs:count(Column#12)->Column#10",
          "└─TableReader 1.00 root  data:ExchangeSender",
          "  └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "    └─HashAgg 1.00 mpp[tiflash]  funcs:count(test.t.d)->Column#12",
          "      └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "select count(1), count(3.1415), count(0), count(null) from t -- every count but count(null) can be rewritten",
        "Plan": [
          "HashAgg 1.00 root  funcs:count(Column#18)->Column#10, funcs:count(Column#19)->Column#11, funcs:count(Column#20)->Column#12, funcs:count(Column#21)->Column#13",
          "└─TableReader 1.00 root  data:ExchangeSender",
          "  └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "    └─HashAgg 1.00 mpp[tiflash]  funcs:count(test.t.d)->Column#18, funcs:count(test.t.d)->Column#19, funcs:count(test.t.d)->Column#20, funcs:count(NULL)->Column#21",
          "      └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "select count(*) from t where a=1",
        "Plan": [
          "HashAgg 1.00 root  funcs:count(Column#12)->Column#10",
          "└─TableReader 1.00 root  data:ExchangeSender",
          "  └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "    └─HashAgg 1.00 mpp[tiflash]  funcs:count(1)->Column#12",
          "      └─Selection 10.00 mpp[tiflash]  eq(test.t.a, 1)",
          "        └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "select count(*) from t_pick_row_id",
        "Plan": [
          "HashAgg 1.00 root  funcs:count(Column#5)->Column#3",
          "└─TableReader 1.00 root  data:ExchangeSender",
          "  └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "    └─HashAgg 1.00 mpp[tiflash]  funcs:count(test.t_pick_row_id._tidb_rowid)->Column#5",
          "      └─TableFullScan 10000.00 mpp[tiflash] table:t_pick_row_id keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "select t.b, t.c from (select count(*) as c from t) a, t where a.c=t.a -- test recursive",
        "Plan": [
          "HashJoin 1.25 root  inner join, equal:[eq(test.t.a, Column#10)]",
          "├─HashAgg(Build) 1.00 root  funcs:count(Column#22)->Column#10",
          "│ └─TableReader 1.00 root  data:ExchangeSender",
          "│   └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "│     └─HashAgg 1.00 mpp[tiflash]  funcs:count(test.t.d)->Column#22",
          "│       └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo",
          "└─TableReader(Probe) 10000.00 root  data:TableFullScan",
          "  └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "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",
        "Plan": [
          "Projection 10000.00 root  test.t.a, test.t.b, test.t.c, test.t.d, test.t.e, test.t.f, test.t.g, test.t.h",
          "└─Apply 10000.00 root  CARTESIAN inner join, other cond:gt(test.t.a, Column#19)",
          "  ├─TableReader(Build) 10000.00 root  data:TableFullScan",
          "  │ └─TableFullScan 10000.00 cop[tiflash] table:out1 keep order:false, stats:pseudo",
          "  └─HashAgg(Probe) 10000.00 root  funcs:count(Column#21)->Column#19",
          "    └─TableReader 10000.00 root  data:ExchangeSender",
          "      └─ExchangeSender 10000.00 mpp[tiflash]  ExchangeType: PassThrough",
          "        └─HashAgg 10000.00 mpp[tiflash]  funcs:count(1)->Column#21",
          "          └─Selection 80000000.00 mpp[tiflash]  eq(cast(test.t.a, double BINARY), cast(test.t.b, double BINARY))",
          "            └─TableFullScan 100000000.00 mpp[tiflash] table:inn keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "select count(*) from t t1, t t2 where t1.a=t2.e -- shouldn't be rewritten when join under agg",
        "Plan": [
          "HashAgg 1.00 root  funcs:count(Column#20)->Column#19",
          "└─TableReader 1.00 root  data:ExchangeSender",
          "  └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "    └─HashAgg 1.00 mpp[tiflash]  funcs:count(1)->Column#20",
          "      └─HashJoin 12500.00 mpp[tiflash]  inner join, equal:[eq(test.t.a, test.t.e)]",
          "        ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash]  ",
          "        │ └─ExchangeSender 10000.00 mpp[tiflash]  ExchangeType: Broadcast",
          "        │   └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo",
          "        └─TableFullScan(Probe) 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "select count(distinct 1) from t -- shouldn't be rewritten",
        "Plan": [
          "TableReader 1.00 root  data:ExchangeSender",
          "└─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─Projection 1.00 mpp[tiflash]  Column#10",
          "    └─HashAgg 1.00 mpp[tiflash]  funcs:count(distinct Column#12)->Column#10",
          "      └─ExchangeReceiver 1.00 mpp[tiflash]  ",
          "        └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "          └─HashAgg 1.00 mpp[tiflash]  group by:1, ",
          "            └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "select count(1), count(a), count(b) from t -- keep count(1)",
        "Plan": [
          "HashAgg 1.00 root  funcs:count(Column#16)->Column#10, funcs:count(Column#17)->Column#11, funcs:count(Column#18)->Column#12",
          "└─TableReader 1.00 root  data:ExchangeSender",
          "  └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "    └─HashAgg 1.00 mpp[tiflash]  funcs:count(1)->Column#16, funcs:count(test.t.a)->Column#17, funcs:count(test.t.b)->Column#18",
          "      └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "select a, count(*) from t group by a -- shouldn't be rewritten",
        "Plan": [
          "TableReader 8000.00 root  data:ExchangeSender",
          "└─ExchangeSender 8000.00 mpp[tiflash]  ExchangeType: PassThrough",
          "  └─Projection 8000.00 mpp[tiflash]  test.t.a, Column#10",
          "    └─Projection 8000.00 mpp[tiflash]  Column#10, test.t.a",
          "      └─HashAgg 8000.00 mpp[tiflash]  group by:test.t.a, funcs:count(1)->Column#10, funcs:firstrow(test.t.a)->test.t.a",
          "        └─ExchangeReceiver 10000.00 mpp[tiflash]  ",
          "          └─ExchangeSender 10000.00 mpp[tiflash]  ExchangeType: HashPartition, Hash Cols: [name: test.t.a, collate: binary]",
          "            └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo"
        ],
        "Warning": null
      },
      {
        "SQL": "select sum(a) from t -- sum shouldn't be rewritten",
        "Plan": [
          "HashAgg 1.00 root  funcs:sum(Column#12)->Column#10",
          "└─TableReader 1.00 root  data:ExchangeSender",
          "  └─ExchangeSender 1.00 mpp[tiflash]  ExchangeType: PassThrough",
          "    └─HashAgg 1.00 mpp[tiflash]  funcs:sum(Column#15)->Column#12",
          "      └─Projection 10000.00 mpp[tiflash]  cast(test.t.a, decimal(10,0) BINARY)->Column#15",
          "        └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo"
        ],
        "Warning": null
      }
    ]
  }
]
