From eabd1de88133c5edacacfdb830005ecf5cd36b18 Mon Sep 17 00:00:00 2001 From: Ti Chi Robot Date: Tue, 11 Jun 2024 18:52:30 +0800 Subject: [PATCH] hint: avoid duplicate hints in QBHintHandler (#53921) (#53937) close pingcap/tidb#53767 --- pkg/planner/core/casetest/hint/BUILD.bazel | 2 +- pkg/planner/core/casetest/hint/hint_test.go | 12 ++++++++++++ .../hint/testdata/integration_suite_out.json | 10 ++-------- .../physicalplantest/testdata/plan_suite_out.json | 10 ++-------- pkg/util/hint/hint_query_block.go | 5 ++++- tests/integrationtest/r/index_merge.result | 1 - 6 files changed, 21 insertions(+), 19 deletions(-) diff --git a/pkg/planner/core/casetest/hint/BUILD.bazel b/pkg/planner/core/casetest/hint/BUILD.bazel index cf2c5aff0e10b..92e2bbbaee2c4 100644 --- a/pkg/planner/core/casetest/hint/BUILD.bazel +++ b/pkg/planner/core/casetest/hint/BUILD.bazel @@ -9,7 +9,7 @@ go_test( ], data = glob(["testdata/**"]), flaky = True, - shard_count = 7, + shard_count = 8, deps = [ "//pkg/config", "//pkg/domain", diff --git a/pkg/planner/core/casetest/hint/hint_test.go b/pkg/planner/core/casetest/hint/hint_test.go index 6a757ec52c80d..8dfba53cf7dcf 100644 --- a/pkg/planner/core/casetest/hint/hint_test.go +++ b/pkg/planner/core/casetest/hint/hint_test.go @@ -372,3 +372,15 @@ func TestHints(t *testing.T) { tk.MustQuery("show warnings").Check(testkit.Rows(output[i].Warn...)) } } + +func TestQBHintHandlerDuplicateObjects(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("CREATE TABLE t_employees (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, fname VARCHAR(25) NOT NULL, lname VARCHAR(25) NOT NULL, store_id INT NOT NULL, department_id INT NOT NULL);") + tk.MustExec("ALTER TABLE t_employees ADD INDEX idx(department_id);") + + // Explain statement + tk.MustQuery("EXPLAIN WITH t AS (SELECT /*+ inl_join(e) */ em.* FROM t_employees em JOIN t_employees e WHERE em.store_id = e.department_id) SELECT * FROM t;") + tk.MustQuery("show warnings").Check(testkit.Rows()) +} diff --git a/pkg/planner/core/casetest/hint/testdata/integration_suite_out.json b/pkg/planner/core/casetest/hint/testdata/integration_suite_out.json index db7113f881942..0707e8f64dc19 100644 --- a/pkg/planner/core/casetest/hint/testdata/integration_suite_out.json +++ b/pkg/planner/core/casetest/hint/testdata/integration_suite_out.json @@ -1449,10 +1449,7 @@ " └─IndexRangeScan_148 19492.21 cop[tikv] table:t1, index:idx_a(a) range: decided by [eq(test.t1.a, test.t1.a)], keep order:false, stats:pseudo" ], "Warn": [ - "[planner:1815]We can only use one leading hint at most, when multiple leading hints are used, all leading hints will be invalid", - "[planner:1815]There are no matching table names for (t1) in optimizer hint /*+ INL_JOIN(t1, t1) */ or /*+ TIDB_INLJ(t1, t1) */. Maybe you can use the table alias name", - "[planner:1815]We can only use one leading hint at most, when multiple leading hints are used, all leading hints will be invalid", - "[planner:1815]There are no matching table names for (t1, t1) in optimizer hint /*+ INL_JOIN(t1, t1, t1) */ or /*+ TIDB_INLJ(t1, t1, t1) */. Maybe you can use the table alias name" + "[planner:1815]We can only use one leading hint at most, when multiple leading hints are used, all leading hints will be invalid" ] }, { @@ -1484,10 +1481,7 @@ " └─TableRowIDScan_69 9990.00 cop[tikv] table:t2 keep order:false, stats:pseudo" ], "Warn": [ - "[planner:1815]We can only use one leading hint at most, when multiple leading hints are used, all leading hints will be invalid", - "[planner:1815]There are no matching table names for (t2) in optimizer hint /*+ MERGE_JOIN(t2, t2) */ or /*+ TIDB_SMJ(t2, t2) */. Maybe you can use the table alias name", - "[planner:1815]We can only use one leading hint at most, when multiple leading hints are used, all leading hints will be invalid", - "[planner:1815]There are no matching table names for (t2, t2) in optimizer hint /*+ MERGE_JOIN(t2, t2, t2) */ or /*+ TIDB_SMJ(t2, t2, t2) */. Maybe you can use the table alias name" + "[planner:1815]We can only use one leading hint at most, when multiple leading hints are used, all leading hints will be invalid" ] }, { diff --git a/pkg/planner/core/casetest/physicalplantest/testdata/plan_suite_out.json b/pkg/planner/core/casetest/physicalplantest/testdata/plan_suite_out.json index 159574fb34ad5..77b158932f3ad 100644 --- a/pkg/planner/core/casetest/physicalplantest/testdata/plan_suite_out.json +++ b/pkg/planner/core/casetest/physicalplantest/testdata/plan_suite_out.json @@ -835,10 +835,7 @@ " └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", " └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo" ], - "Warn": [ - "[planner:1815]There are no matching table names for (t1, t) in optimizer hint /*+ SHUFFLE_JOIN(t1, t, t1, t) */ or /*+ SHUFFLE_JOIN(t1, t, t1, t) */. Maybe you can use the table alias name", - "[planner:1815]There are no matching table names for (t1, t, t1, t) in optimizer hint /*+ SHUFFLE_JOIN(t1, t, t1, t, t1, t) */ or /*+ SHUFFLE_JOIN(t1, t, t1, t, t1, t) */. Maybe you can use the table alias name" - ] + "Warn": null }, { "SQL": "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;", @@ -868,10 +865,7 @@ " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.a))", " └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo" ], - "Warn": [ - "[planner:1815]There are no matching table names for (t1, t) in optimizer hint /*+ BROADCAST_JOIN(t1, t, t1, t) */ or /*+ TIDB_BCJ(t1, t, t1, t) */. Maybe you can use the table alias name", - "[planner:1815]There are no matching table names for (t1, t, t1, t) in optimizer hint /*+ BROADCAST_JOIN(t1, t, t1, t, t1, t) */ or /*+ TIDB_BCJ(t1, t, t1, t, t1, t) */. Maybe you can use the table alias name" - ] + "Warn": null }, { "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), broadcast_join(t1, t2), hash_join_build(t2) */ * from t t1 left join t t2 on t1.a=t2.a", diff --git a/pkg/util/hint/hint_query_block.go b/pkg/util/hint/hint_query_block.go index c9620fb96e078..99bfc646837e6 100644 --- a/pkg/util/hint/hint_query_block.go +++ b/pkg/util/hint/hint_query_block.go @@ -16,6 +16,7 @@ package hint import ( "fmt" + "slices" "strconv" "strings" @@ -295,7 +296,9 @@ func (p *QBHintHandler) GetCurrentStmtHints(hints []*ast.TableOptimizerHint, cur } continue } - p.QBOffsetToHints[offset] = append(p.QBOffsetToHints[offset], hint) + if !slices.Contains(p.QBOffsetToHints[offset], hint) { + p.QBOffsetToHints[offset] = append(p.QBOffsetToHints[offset], hint) + } } return p.QBOffsetToHints[currentOffset] } diff --git a/tests/integrationtest/r/index_merge.result b/tests/integrationtest/r/index_merge.result index 986112abaee60..97413da357a9d 100644 --- a/tests/integrationtest/r/index_merge.result +++ b/tests/integrationtest/r/index_merge.result @@ -852,7 +852,6 @@ show warnings; Level Code Message Warning 1815 use_index_merge(index_merge.t_alias) is inapplicable, check whether the table(index_merge.t_alias) exists Warning 1815 use_index_merge(index_merge.t_alias) is inapplicable, check whether the table(index_merge.t_alias) exists -Warning 1815 use_index_merge(index_merge.t_alias) is inapplicable, check whether the table(index_merge.t_alias) exists with recursive cte1 as (select 1 c1, 1 c2, 1 c3 UNION ALL select /*+ use_index_merge(t_alias) */ c1 + 1, c2 + 1, c3 + 1 from cte1 t_alias where c1 < 10 or c2 < 10 and c3 < 10) select * from cte1 order by 1; c1 c2 c3 1 1 1