[
  {
    "name": "TestPushLimitDownIndexLookUpReader",
    "cases": [
      // Limit should be pushed down into IndexLookUpReader, row count of IndexLookUpReader and TableScan should be 1.00.
      "explain select * from tbl use index(idx_b_c) where b > 1 limit 2,1",
      // Projection atop IndexLookUpReader, Limit should be pushed down into IndexLookUpReader, and Projection should have row count 1.00 as well.
      "explain select * from tbl use index(idx_b_c) where b > 1 order by b desc limit 2,1",
      // Limit should be pushed down into IndexLookUpReader when Selection on top of IndexScan.
      "explain select * from tbl use index(idx_b_c) where b > 1 and c > 1 limit 2,1",
      // Limit should NOT be pushed down into IndexLookUpReader when Selection on top of TableScan.
      "explain select * from tbl use index(idx_b_c) where b > 1 and a > 1 limit 2,1"
    ]
  },
  {
    "name": "TestIsFromUnixtimeNullRejective",
    "cases": [
      // fix #12385
      "explain select * from t t1 left join t t2 on t1.a=t2.a where from_unixtime(t2.b);"
    ]
  },
  {
    "name": "TestAggColumnPrune",
    "cases": [
      "select count(1) from t join (select count(1) from t where false) as tmp",
      "select count(1) from t join (select max(a) from t where false) as tmp",
      "select count(1) from t join (select min(a) from t where false) as tmp",
      "select count(1) from t join (select sum(a) from t where false) as tmp",
      "select count(1) from t join (select avg(a) from t where false) as tmp",
      "select count(1) from t join (select count(1) from t where false group by a) as tmp",
      "select count(1) from t join (select max(a) from t where false group by a) as tmp",
      "select count(1) from t join (select min(a) from t where false group by a) as tmp",
      "select count(1) from t join (select sum(a) from t where false group by a) as tmp",
      "select count(1) from t join (select avg(a) from t where false group by a) as tmp",
      "SELECT avg(2) FROM(SELECT min(c) FROM t JOIN(SELECT 1 c) d ORDER BY a) e"
    ]
  },
  {
    "name": "TestSimplifyOuterJoinWithCast",
    "cases": [
      // LeftOuterJoin should no be simplified to InnerJoin.
      "explain select * from t t1 left join t t2 on t1.a = t2.a where cast(t1.b as date) >= '2019-01-01'"
    ]
  },
  {
    "name": "TestMaxMinEliminate",
    "cases": [
      "explain (select max(a) from t) union (select min(a) from t)"
    ]
  },
  {
    "name": "TestIndexJoinUniqueCompositeIndex",
    "cases": [
      // Row count of IndexScan should be 2.
      "explain select /*+ TIDB_INLJ(t2) */ * from t1 join t2 on t1.a = t2.a and t1.c = t2.c",
      // Row count of IndexScan should be 2.
      "explain select /*+ TIDB_INLJ(t2) */ * from t1 join t2 on t1.a = t2.a and t1.c <= t2.b",
      // Row count of IndexScan should be 1.
      "explain select /*+ TIDB_INLJ(t2) */ * from t1 join t2 on t1.a = t2.a and t2.b = 1"
    ]
  },
  {
    "name": "TestPartitionTableStats",
    "cases": [
      "explain select * from t order by a",
      "select * from t order by a",
      "explain select * from t order by a limit 3",
      "select * from t order by a limit 3"
    ]
  },
  {
    "name": "TestIndexMerge",
    "cases": [
      "explain select /*+ USE_INDEX_MERGE(t, a, b) */ * from t where a = 1 or b = 2",
      "explain select /*+ USE_INDEX_MERGE(t, primary) */ * from t where 1 or t.c",
      "explain select /*+ USE_INDEX_MERGE(t, a, b, c) */ * from t where 1 or t.a = 1 or t.b = 2"
    ]
  },
  {
    "name": "TestSubqueryWithTopN",
    "cases": [
      "desc select t1.b from t t1 where t1.b in (select t2.a from t t2 order by t1.a+t2.a limit 1)",
      "desc select t1.a from t t1 order by (t1.b = 1 and exists (select 1 from t t2 where t1.b = t2.b)) limit 1",
      "desc select * from (select b+b as x from t) t1, t t2 where t1.x=t2.b order by t1.x limit 1"
    ]
  },
  {
    "name": "TestIndexJoinTableRange",
    "cases": [
      "desc select /*+ TIDB_INLJ(t2)*/ * from t1, t2 where t1.a = t2.a and t1.b = t2.b",
      "desc select /*+ TIDB_INLJ(t2)*/ * from t1, t2 where t1.a = t2.a and t1.b = t2.a and t1.b = t2.b"
    ]
  },
  {
    "name": "TestHintWithRequiredProperty",
    "cases": [
      "desc select /*+ INL_JOIN(t2) */ * from t t1, t t2 where t1.a = t2.b order by t2.a",
      "desc select /*+ INL_HASH_JOIN(t2) */ * from t t1, t t2 where t1.a = t2.b order by t2.a",
      "desc select /*+ INL_MERGE_JOIN(t2)*/ t1.a, t2.a from t t1, t t2 ,t t3 where t1.a = t2.a and t3.a=t2.a",
      "desc select * from t t1, (select /*+ HASH_AGG() */ b, max(a) from t t2 group by b) t2 where t1.b = t2.b order by t1.b",
      "desc select /*+ INL_HASH_JOIN(t2) */ distinct t2.a from t t1 join t t2 on t1.a = t2.a",
      // This hint cannot work, so choose another plan.
      "desc select /*+ INL_JOIN(t2) */ * from t t1, t t2 where t1.a = t2.c order by t1.a"
    ]
  },
  {
    "name": "TestIndexHintWarning",
    "cases": [
      "select /*+ USE_INDEX(t1, j) */ * from t1",
      "select /*+ IGNORE_INDEX(t1, j) */ * from t1",
      "select /*+ USE_INDEX(t2, a, b, c) */ * from t1",
      "select /*+ USE_INDEX(t2) */ * from t1",
      "select /*+ USE_INDEX(t1, a), USE_INDEX(t2, a), USE_INDEX(t3, a) */ * from t1, t2 where t1.a=t2.a",
      "select /*+ USE_INDEX(t3, a), USE_INDEX(t4, b), IGNORE_INDEX(t3, a) */ * from t1, t2 where t1.a=t2.a",
      "select /*+ USE_INDEX_MERGE(t3, a, b, d) */ * from t1",
      "select /*+ USE_INDEX_MERGE(t1, a, b, c, d) */ * from t1",
      "select /*+ USE_INDEX_MERGE(t1, a, b), USE_INDEX(t1, a) */ * from t1",
      "select /*+ USE_INDEX_MERGE(t1, a, b), IGNORE_INDEX(t1, a) */ * from t1",
      "select /*+ USE_INDEX_MERGE(t1, primary, a, b, c) */ * from t1"
    ]
  },
  {
    "name": "TestHintWithoutTableWarning",
    "cases": [
      "select /*+ TIDB_SMJ() */ * from t1, t2 where t1.a=t2.a",
      "select /*+ MERGE_JOIN() */ * from t1, t2 where t1.a=t2.a",
      "select /*+ INL_JOIN() */ * from t1, t2 where t1.a=t2.a",
      "select /*+ TIDB_INLJ() */ * from t1, t2 where t1.a=t2.a",
      "select /*+ INL_HASH_JOIN() */ * from t1, t2 where t1.a=t2.a",
      "select /*+ INL_MERGE_JOIN() */ * from t1, t2 where t1.a=t2.a",
      "select /*+ HASH_JOIN() */ * from t1, t2 where t1.a=t2.a",
      "select /*+ USE_INDEX() */ * from t1, t2 where t1.a=t2.a",
      "select /*+ IGNORE_INDEX() */ * from t1, t2 where t1.a=t2.a",
      "select /*+ USE_INDEX_MERGE() */ * from t1, t2 where t1.a=t2.a"
    ]
  },
  {
    "name": "TestPartitionPruningForInExpr",
    "cases": [
      "explain select * from t where a in (1, 2,'11')",
      "explain select * from t where a in (17, null)",
      "explain select * from t where a in (16, 'abc')",
      "explain select * from t where a in (15, 0.12, 3.47)",
      "explain select * from t where a in (0.12, 3.47)",
      "explain select * from t where a in (14, floor(3.47))",
      "explain select * from t where b in (3, 4)"
    ]
  },
  {
    "name": "TestStreamAggProp",
    "cases": [
      "select /*+ stream_agg() */ count(*) c from t group by a order by c limit 1",
      "select /*+ stream_agg() */ count(*) c from t group by a order by c",
      "select /*+ stream_agg() */ count(*) c from t group by a order by a limit 1",
      "select /*+ stream_agg() */ count(*) c from t group by a order by a"
    ]
  },
  {
    "name": "TestOptimizeHintOnPartitionTable",
    "cases": [
      "select /*+ use_index(t) */ * from t",
      "select /*+ use_index(t partition(p0, p1) b, c) */ * from t partition(p1,p2)",
      "select /*+ use_index(t partition(p_non_exist)) */ * from t partition(p1,p2)",
      "select /*+ use_index(t partition(p0, p1) b, c) */ * from t",
      "select /*+ ignore_index(t partition(p0, p1) b, c) */ * from t",
      "select /*+ hash_join(t1, t2 partition(p0)) */ * from t t1 join t t2 on t1.a = t2.a",
      "select /*+ use_index_merge(t partition(p0)) */ * from t where t.b = 1 or t.c = \"8\"",
      "select /*+ use_index_merge(t partition(p0, p1) primary, b) */ * from t where t.a = 1 or t.b = 2",
      "select /*+ use_index(t partition(p0) b) */ * from t partition(p0, p1)",
      "select /*+ read_from_storage(tikv[t partition(p0)], tiflash[t partition(p1, p2)]) */ * from t"
    ]
  },
  {
    "name": "TestApproxPercentile",
    "cases": [
      "select approx_percentile(a, 50) from t",
      "select approx_percentile(a, 10) from t",
      "select approx_percentile(a, 10+70) from t",
      "select approx_percentile(a, 10*10) from t",
      "select approx_percentile(a, 50) from t group by b order by b"
    ]
  },
  {
    "name": "TestIssue22105",
    "cases": [
      "explain SELECT /*+ use_index_merge(t1)*/ COUNT(*) FROM t1 WHERE (key4=42 AND key6 IS NOT NULL) OR (key1=4 AND key3=6)"
    ]
  },
  {
    "name": "TestReorderSimplifiedOuterJoins",
    "cases": [
      // Query with INNER JOIN or LEFT JOIN should have the same plan.
      "EXPLAIN SELECT t1.pk FROM t1 INNER JOIN t2 ON t1.col1 = t2.pk INNER JOIN t3 ON t1.col3 = t3.pk WHERE t2.col1 IN ('a' , 'b') AND t3.keycol = 'c' AND t1.col2 = 'a' AND t1.col1 != 'abcdef' AND t1.col1 != 'aaaaaa'",
      "EXPLAIN SELECT t1.pk FROM t1 LEFT JOIN t2 ON t1.col1 = t2.pk LEFT JOIN t3 ON t1.col3 = t3.pk WHERE t2.col1 IN ('a' , 'b') AND t3.keycol = 'c' AND t1.col2 = 'a' AND t1.col1 != 'abcdef' AND t1.col1 != 'aaaaaa'"
    ]
  }
]
