diff --git a/planner/core/casetest/physical_plan_test.go b/planner/core/casetest/physical_plan_test.go index 1023fb0a15..eaad864e8c 100644 --- a/planner/core/casetest/physical_plan_test.go +++ b/planner/core/casetest/physical_plan_test.go @@ -652,6 +652,36 @@ func TestUnmatchedTableInHint(t *testing.T) { } } +func TestIssue37520(t *testing.T) { + store := testkit.CreateMockStore(t, internal.WithMockTiFlash(2)) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set tidb_cost_model_version=2") + tk.MustExec("drop table if exists t1, t2") + tk.MustExec("create table t1(a int primary key, b int);") + tk.MustExec("create table t2(a int, b int, index ia(a));") + + var input []string + var output []struct { + SQL string + Plan []string + Warn []string + } + + planSuiteData := GetPlanSuiteData() + planSuiteData.LoadTestCases(t, &input, &output) + + for i, ts := range input { + testdata.OnRecord(func() { + output[i].SQL = ts + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + ts).Rows()) + output[i].Warn = testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings()) + }) + tk.MustQuery("explain format = 'brief' " + ts).Check(testkit.Rows(output[i].Plan...)) + require.Equal(t, output[i].Warn, testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings())) + } +} + func TestMPPHints(t *testing.T) { store := testkit.CreateMockStore(t, internal.WithMockTiFlash(2)) tk := testkit.NewTestKit(t, store) diff --git a/planner/core/casetest/testdata/join_reorder_suite_out.json b/planner/core/casetest/testdata/join_reorder_suite_out.json index 58336dc72d..d43d072d43 100644 --- a/planner/core/casetest/testdata/join_reorder_suite_out.json +++ b/planner/core/casetest/testdata/join_reorder_suite_out.json @@ -6476,7 +6476,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t3) */. Maybe you can use the table alias name" + "Warning 1815 leading hint is inapplicable, check the join type or the join algorithm hint" ] }, { @@ -6495,7 +6495,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t2, t3) */. Maybe you can use the table alias name", + "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" ] }, @@ -6515,7 +6515,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t1, t3) */. Maybe you can use the table alias name", + "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" ] }, @@ -6535,7 +6535,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t3, t2) */. Maybe you can use the table alias name", + "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" ] }, @@ -6555,7 +6555,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t3, t1) */. Maybe you can use the table alias name", + "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" ] }, @@ -6595,7 +6595,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t3) */. Maybe you can use the table alias name" + "Warning 1815 leading hint is inapplicable, check the join type or the join algorithm hint" ] }, { @@ -6613,7 +6613,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t2, t3) */. Maybe you can use the table alias name", + "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" ] }, @@ -6632,7 +6632,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t1, t3) */. Maybe you can use the table alias name", + "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" ] }, @@ -6651,7 +6651,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t3, t2) */. Maybe you can use the table alias name", + "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" ] }, @@ -6670,7 +6670,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t3, t1) */. Maybe you can use the table alias name", + "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" ] }, @@ -6712,7 +6712,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t3) */. Maybe you can use the table alias name" + "Warning 1815 leading hint is inapplicable, check the join type or the join algorithm hint" ] }, { @@ -6731,7 +6731,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t2, t3) */. Maybe you can use the table alias name", + "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" ] }, @@ -6751,7 +6751,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t1, t3) */. Maybe you can use the table alias name", + "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" ] }, @@ -6771,7 +6771,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t3, t2) */. Maybe you can use the table alias name", + "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" ] }, @@ -6791,7 +6791,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t3, t1) */. Maybe you can use the table alias name", + "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" ] }, @@ -6831,7 +6831,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t3) */. Maybe you can use the table alias name" + "Warning 1815 leading hint is inapplicable, check the join type or the join algorithm hint" ] }, { @@ -6849,7 +6849,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t2, t3) */. Maybe you can use the table alias name", + "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" ] }, @@ -6868,7 +6868,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t1, t3) */. Maybe you can use the table alias name", + "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" ] }, @@ -6887,7 +6887,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t3, t2) */. Maybe you can use the table alias name", + "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" ] }, @@ -6906,7 +6906,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t3, t1) */. Maybe you can use the table alias name", + "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" ] }, @@ -7426,7 +7426,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t3) */. Maybe you can use the table alias name" + "Warning 1815 leading hint is inapplicable, check the join type or the join algorithm hint" ] }, { @@ -7444,7 +7444,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t2, t3) */. Maybe you can use the table alias name", + "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" ] }, @@ -7463,7 +7463,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t1, t3) */. Maybe you can use the table alias name", + "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" ] }, @@ -7482,7 +7482,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t3, t2) */. Maybe you can use the table alias name", + "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" ] }, @@ -7501,7 +7501,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t3, t1) */. Maybe you can use the table alias name", + "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" ] }, @@ -8881,7 +8881,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t3) */. Maybe you can use the table alias name" + "Warning 1815 leading hint is inapplicable, check the join type or the join algorithm hint" ] }, { @@ -8900,7 +8900,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t2, t3) */. Maybe you can use the table alias name", + "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" ] }, @@ -8937,7 +8937,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t3) */. Maybe you can use the table alias name" + "Warning 1815 leading hint is inapplicable, check the join type or the join algorithm hint" ] }, { @@ -8954,7 +8954,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t2, t3) */. Maybe you can use the table alias name", + "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" ] }, @@ -8996,7 +8996,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t3) */. Maybe you can use the table alias name" + "Warning 1815 leading hint is inapplicable, check the join type or the join algorithm hint" ] }, { @@ -9015,7 +9015,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t2, t3) */. Maybe you can use the table alias name", + "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" ] }, @@ -9052,7 +9052,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t3) */. Maybe you can use the table alias name" + "Warning 1815 leading hint is inapplicable, check the join type or the join algorithm hint" ] }, { @@ -9069,7 +9069,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t2, t3) */. Maybe you can use the table alias name", + "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" ] }, @@ -9438,7 +9438,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t3) */. Maybe you can use the table alias name" + "Warning 1815 leading hint is inapplicable, check the join type or the join algorithm hint" ] }, { @@ -9456,7 +9456,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ], "Warning": [ - "Warning 1815 There are no matching table names for (t3) in optimizer hint /*+ LEADING(t2, t3) */. Maybe you can use the table alias name", + "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" ] }, diff --git a/planner/core/casetest/testdata/plan_suite_in.json b/planner/core/casetest/testdata/plan_suite_in.json index ec93e0c399..2d76c71377 100644 --- a/planner/core/casetest/testdata/plan_suite_in.json +++ b/planner/core/casetest/testdata/plan_suite_in.json @@ -52,8 +52,8 @@ "select /*+ qb_name(qb, v1), broadcast_join(t1@qb, t2@qb) */ * from v1", // Subquery hint - "SELECT /*+ shuffle_join(t) */ * FROM t WHERE EXISTS (SELECT /*+ SEMI_JOIN_REWRITE */ 1 FROM t t1 WHERE t1.b = t.b);", - "SELECT /*+ broadcast_join(t) */ * FROM t WHERE EXISTS (SELECT /*+ SEMI_JOIN_REWRITE */ 1 FROM t t1 WHERE t1.b = t.b);", + "SELECT /*+ shuffle_join(t) */ * FROM t WHERE EXISTS (SELECT /*+ SEMI_JOIN_REWRITE() */ 1 FROM t t1 WHERE t1.b = t.b);", + "SELECT /*+ broadcast_join(t) */ * FROM t WHERE EXISTS (SELECT /*+ SEMI_JOIN_REWRITE() */ 1 FROM t t1 WHERE t1.b = t.b);", "select * from t t1 where t1.a < (select /*+ MPP_1PHASE_AGG() */ sum(t2.a) from t t2 where t2.b = t1.b);", "select * from t t1 where t1.a < (select /*+ MPP_2PHASE_AGG() */ sum(t2.a) from t t2 where t2.b = t1.b);", @@ -68,6 +68,15 @@ "WITH CTE AS (SELECT /*+ MERGE(), broadcast_join(t1, t) */ t.a, t.b FROM t join t t1 where t.a = t1.a) SELECT * FROM CTE WHERE CTE.a <18 union select * from cte where cte.b > 1;" ] }, + { + "name": "TestIssue37520", + "cases": [ + "select /*+ inl_join(t1@sel_2) */ a, (select b from t1 where t1.a = t2.b) from t2;", + "select /*+ inl_join(t2) */ a, (select b from t1 where t1.a = t2.b) from t2;", + "select /*+ inl_join(t2@sel_2) */ * from t1 where exists ( select /*+ semi_join_rewrite() */ * from t2 where t1.a = t2.a);", + "select /*+ inl_join(t1) */ * from t1 where exists ( select /*+ semi_join_rewrite() */ * from t2 where t1.a = t2.a);" + ] + }, { "name": "TestHintScope", "cases": [ diff --git a/planner/core/casetest/testdata/plan_suite_out.json b/planner/core/casetest/testdata/plan_suite_out.json index 86ee4c5125..ef942eba14 100644 --- a/planner/core/casetest/testdata/plan_suite_out.json +++ b/planner/core/casetest/testdata/plan_suite_out.json @@ -554,40 +554,46 @@ "Warn": null }, { - "SQL": "SELECT /*+ shuffle_join(t) */ * FROM t WHERE EXISTS (SELECT /*+ SEMI_JOIN_REWRITE */ 1 FROM t t1 WHERE t1.b = t.b);", + "SQL": "SELECT /*+ shuffle_join(t) */ * FROM t WHERE EXISTS (SELECT /*+ SEMI_JOIN_REWRITE() */ 1 FROM t t1 WHERE t1.b = t.b);", "Plan": [ - "TableReader 7992.00 root MppVersion: 1, data:ExchangeSender", - "└─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: PassThrough", - " └─HashJoin 7992.00 mpp[tiflash] semi join, equal:[eq(test.t.b, test.t.b)]", - " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", - " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast", - " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.b))", - " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo", - " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.b))", - " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + "TableReader 9990.00 root MppVersion: 1, data:ExchangeSender", + "└─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 9990.00 mpp[tiflash] test.t.a, test.t.b, test.t.c", + " └─HashJoin 9990.00 mpp[tiflash] inner join, equal:[eq(test.t.b, test.t.b)]", + " ├─Projection(Build) 7992.00 mpp[tiflash] test.t.b", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.b, funcs:firstrow(test.t.b)->test.t.b", + " │ └─ExchangeReceiver 7992.00 mpp[tiflash] ", + " │ └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.b, collate: binary]", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.b, ", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.b))", + " │ └─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, Compression: FAST, Hash Cols: [name: test.t.b, collate: binary]", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.b))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" ], - "Warn": [ - "[planner:1815]There are no matching table names for (t) in optimizer hint /*+ SHUFFLE_JOIN(t) */ or /*+ SHUFFLE_JOIN(t) */. Maybe you can use the table alias name", - "[parser:1064]Optimizer hint syntax error at line 1 column 109 near \"\" " - ] + "Warn": null }, { - "SQL": "SELECT /*+ broadcast_join(t) */ * FROM t WHERE EXISTS (SELECT /*+ SEMI_JOIN_REWRITE */ 1 FROM t t1 WHERE t1.b = t.b);", + "SQL": "SELECT /*+ broadcast_join(t) */ * FROM t WHERE EXISTS (SELECT /*+ SEMI_JOIN_REWRITE() */ 1 FROM t t1 WHERE t1.b = t.b);", "Plan": [ - "TableReader 7992.00 root MppVersion: 1, data:ExchangeSender", - "└─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: PassThrough", - " └─HashJoin 7992.00 mpp[tiflash] semi join, equal:[eq(test.t.b, test.t.b)]", - " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", - " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast", - " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.b))", - " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo", - " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.b))", - " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + "TableReader 9990.00 root MppVersion: 1, data:ExchangeSender", + "└─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 9990.00 mpp[tiflash] test.t.a, test.t.b, test.t.c", + " └─HashJoin 9990.00 mpp[tiflash] inner join, equal:[eq(test.t.b, test.t.b)]", + " ├─ExchangeReceiver(Build) 7992.00 mpp[tiflash] ", + " │ └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Projection 7992.00 mpp[tiflash] test.t.b", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.b, funcs:firstrow(test.t.b)->test.t.b", + " │ └─ExchangeReceiver 7992.00 mpp[tiflash] ", + " │ └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.b, collate: binary]", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.b, ", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.b))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.b))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" ], - "Warn": [ - "[planner:1815]There are no matching table names for (t) in optimizer hint /*+ BROADCAST_JOIN(t) */ or /*+ TIDB_BCJ(t) */. Maybe you can use the table alias name", - "[parser:1064]Optimizer hint syntax error at line 1 column 111 near \"\" " - ] + "Warn": null }, { "SQL": "select * from t t1 where t1.a < (select /*+ MPP_1PHASE_AGG() */ sum(t2.a) from t t2 where t2.b = t1.b);", @@ -855,6 +861,63 @@ } ] }, + { + "Name": "TestIssue37520", + "Cases": [ + { + "SQL": "select /*+ inl_join(t1@sel_2) */ a, (select b from t1 where t1.a = t2.b) from t2;", + "Plan": [ + "IndexJoin 12500.00 root left outer join, inner:TableReader, outer key:test.t2.b, inner key:test.t1.a, equal cond:eq(test.t2.b, test.t1.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:TableRangeScan", + " └─TableRangeScan 10000.00 cop[tikv] table:t1 range: decided by [test.t2.b], keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ inl_join(t2) */ a, (select b from t1 where t1.a = t2.b) from t2;", + "Plan": [ + "HashJoin 12500.00 root left outer join, equal:[eq(test.t2.b, 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:t2 keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]Optimizer Hint /*+ INL_JOIN(t2) */ or /*+ TIDB_INLJ(t2) */ is inapplicable" + ] + }, + { + "SQL": "select /*+ inl_join(t2@sel_2) */ * from t1 where exists ( select /*+ semi_join_rewrite() */ * from t2 where t1.a = t2.a);", + "Plan": [ + "MergeJoin 9990.00 root inner join, left key:test.t1.a, right key:test.t2.a", + "├─StreamAgg(Build) 7992.00 root group by:test.t2.a, funcs:firstrow(test.t2.a)->test.t2.a", + "│ └─IndexReader 7992.00 root index:StreamAgg", + "│ └─StreamAgg 7992.00 cop[tikv] group by:test.t2.a, ", + "│ └─IndexFullScan 9990.00 cop[tikv] table:t2, index:ia(a) keep order:true, stats:pseudo", + "└─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo" + ], + "Warn": [ + "[planner:1815]Optimizer Hint /*+ INL_JOIN(t2) */ or /*+ TIDB_INLJ(t2) */ is inapplicable" + ] + }, + { + "SQL": "select /*+ inl_join(t1) */ * from t1 where exists ( select /*+ semi_join_rewrite() */ * from t2 where t1.a = t2.a);", + "Plan": [ + "IndexJoin 9990.00 root inner join, inner:TableReader, outer key:test.t2.a, inner key:test.t1.a, equal cond:eq(test.t2.a, test.t1.a)", + "├─StreamAgg(Build) 7992.00 root group by:test.t2.a, funcs:firstrow(test.t2.a)->test.t2.a", + "│ └─IndexReader 7992.00 root index:StreamAgg", + "│ └─StreamAgg 7992.00 cop[tikv] group by:test.t2.a, ", + "│ └─IndexFullScan 9990.00 cop[tikv] table:t2, index:ia(a) keep order:true, stats:pseudo", + "└─TableReader(Probe) 7992.00 root data:TableRangeScan", + " └─TableRangeScan 7992.00 cop[tikv] table:t1 range: decided by [test.t2.a], keep order:false, stats:pseudo" + ], + "Warn": null + } + ] + }, { "Name": "TestHintScope", "Cases": [ diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index c34e63fc82..e99103ce0f 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -5300,6 +5300,7 @@ func (b *PlanBuilder) buildApplyWithJoinType(outerPlan, innerPlan LogicalPlan, t for i := outerPlan.Schema().Len(); i < ap.Schema().Len(); i++ { ap.names[i] = types.EmptyName } + ap.LogicalJoin.setPreferredJoinTypeAndOrder(b.TableHints()) return ap } @@ -5341,7 +5342,8 @@ func setIsInApplyForCTE(p LogicalPlan, apSchema *expression.Schema) { } func (b *PlanBuilder) buildMaxOneRow(p LogicalPlan) LogicalPlan { - maxOneRow := LogicalMaxOneRow{}.Init(b.ctx, b.getSelectOffset()) + // The query block of the MaxOneRow operator should be the same as that of its child. + maxOneRow := LogicalMaxOneRow{}.Init(b.ctx, p.SelectBlockOffset()) maxOneRow.SetChildren(p) return maxOneRow } @@ -5377,42 +5379,7 @@ func (b *PlanBuilder) buildSemiJoin(outerPlan, innerPlan LogicalPlan, onConditio } } // Apply forces to choose hash join currently, so don't worry the hints will take effect if the semi join is in one apply. - if b.TableHints() != nil { - hintInfo := b.TableHints() - outerAlias := extractTableAlias(outerPlan, joinPlan.blockOffset) - innerAlias := extractTableAlias(innerPlan, joinPlan.blockOffset) - if hintInfo.ifPreferMergeJoin(outerAlias, innerAlias) { - joinPlan.preferJoinType |= preferMergeJoin - } - if hintInfo.ifPreferHashJoin(outerAlias, innerAlias) { - joinPlan.preferJoinType |= preferHashJoin - } - if hintInfo.ifPreferINLJ(innerAlias) { - joinPlan.preferJoinType = preferRightAsINLJInner - } - if hintInfo.ifPreferINLHJ(innerAlias) { - joinPlan.preferJoinType = preferRightAsINLHJInner - } - if hintInfo.ifPreferINLMJ(innerAlias) { - joinPlan.preferJoinType = preferRightAsINLMJInner - } - if hintInfo.ifPreferHJBuild(outerAlias) { - joinPlan.preferJoinType |= preferLeftAsHJBuild - } - if hintInfo.ifPreferHJBuild(innerAlias) { - joinPlan.preferJoinType |= preferRightAsHJBuild - } - if hintInfo.ifPreferHJProbe(outerAlias) { - joinPlan.preferJoinType |= preferLeftAsHJProbe - } - if hintInfo.ifPreferHJProbe(innerAlias) { - joinPlan.preferJoinType |= preferRightAsHJProbe - } - // If there're multiple join hints, they're conflict. - if bits.OnesCount(joinPlan.preferJoinType) > 1 { - return nil, errors.New("Join hints are conflict, you can only specify one type of join") - } - } + joinPlan.setPreferredJoinTypeAndOrder(b.TableHints()) if forceRewrite { joinPlan.preferJoinType |= preferRewriteSemiJoin b.optFlag |= flagSemiJoinRewrite