diff --git a/pkg/bindinfo/BUILD.bazel b/pkg/bindinfo/BUILD.bazel index a2cff9a8af..d1f80a9559 100644 --- a/pkg/bindinfo/BUILD.bazel +++ b/pkg/bindinfo/BUILD.bazel @@ -59,7 +59,7 @@ go_test( embed = [":bindinfo"], flaky = True, race = "on", - shard_count = 47, + shard_count = 48, deps = [ "//pkg/bindinfo/internal", "//pkg/config", diff --git a/pkg/bindinfo/universal_binding_test.go b/pkg/bindinfo/universal_binding_test.go index d87611803d..f424ca7797 100644 --- a/pkg/bindinfo/universal_binding_test.go +++ b/pkg/bindinfo/universal_binding_test.go @@ -234,6 +234,28 @@ func TestUniversalBindingSwitch(t *testing.T) { tk3.MustQuery(`show global variables like 'tidb_opt_enable_universal_binding'`).Check(testkit.Rows("tidb_opt_enable_universal_binding OFF")) } +func TestUniversalBindingDBInHints(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec(`use test`) + tk.MustExec(`create table t1 (a int, b int, c int, d int, key(a), key(b), key(c), key(d))`) + tk.MustExec(`create table t2 (a int, b int, c int, d int, key(a), key(b), key(c), key(d))`) + tk.MustExec(`create table t3 (a int, b int, c int, d int, key(a), key(b), key(c), key(d))`) + + tk.MustExec(`create universal binding using select /*+ use_index(test.t, a) */ * from t`) + tk.MustExec(`create universal binding using select /*+ leading(t1, test.t2) */ * from t1, t2 where t1.a=t2.a`) + tk.MustExec(`create universal binding using select /*+ leading(test.t1, test.t2, test.t3) */ * from t1, t2 where t1.a=t2.a and t2.b=t3.b`) + + // use_index(test.t, a) --> use_index(t, a) + // leading(t1, test.t2) --> leading(t1, t2) + // leading(test.t1, test.t2, test.t3) --> leading(t1, t2, t3) + rs := showBinding(tk, "show bindings") + require.Equal(t, len(rs), 3) + require.Equal(t, rs[0][1], "SELECT /*+ leading(`t1`, `t2`)*/ * FROM (`t1`) JOIN `t2` WHERE `t1`.`a` = `t2`.`a`") + require.Equal(t, rs[1][1], "SELECT /*+ leading(`t1`, `t2`, `t3`)*/ * FROM (`t1`) JOIN `t2` WHERE `t1`.`a` = `t2`.`a` AND `t2`.`b` = `t3`.`b`") + require.Equal(t, rs[2][1], "SELECT /*+ use_index(`t` `a`)*/ * FROM `t`") +} + func TestUniversalBindingGC(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) @@ -356,26 +378,25 @@ func TestUniversalBindingHints(t *testing.T) { {`create universal binding using select /*+ inl_join(t2) */ * from t1, t2, t3 where t1.a=t2.a and t3.b=t2.b`, `select * from t1, %st2, t3 where t1.a=t2.a and t3.b=t2.b`}, - // TODO: no_xxx_join hints are not compatible with bindings, fix later. // no join type hint - //{`create universal binding using select /*+ no_hash_join(t1) */ * from t1, t2 where t1.b=t2.b`, - // `select * from %st1, t2 where t1.b=t2.b`}, - //{`create universal binding using select /*+ no_hash_join(t2) */ * from t1, t2 where t1.c=t2.c`, - // `select * from t1, %st2 where t1.c=t2.c`}, - //{`create universal binding using select /*+ no_hash_join(t2) */ * from t1, t2, t3 where t1.a=t2.a and t3.b=t2.b`, - // `select * from t1, %st2, t3 where t1.a=t2.a and t3.b=t2.b`}, - //{`create universal binding using select /*+ no_merge_join(t1) */ * from t1, t2 where t1.b=t2.b`, - // `select * from %st1, t2 where t1.b=t2.b`}, - //{`create universal binding using select /*+ no_merge_join(t2) */ * from t1, t2 where t1.c=t2.c`, - // `select * from t1, %st2 where t1.c=t2.c`}, - //{`create universal binding using select /*+ no_merge_join(t2) */ * from t1, t2, t3 where t1.a=t2.a and t3.b=t2.b`, - // `select * from t1, %st2, t3 where t1.a=t2.a and t3.b=t2.b`}, - //{`create universal binding using select /*+ no_index_join(t1) */ * from t1, t2 where t1.b=t2.b`, - // `select * from %st1, t2 where t1.b=t2.b`}, - //{`create universal binding using select /*+ no_index_join(t2) */ * from t1, t2 where t1.c=t2.c`, - // `select * from t1, %st2 where t1.c=t2.c`}, - //{`create universal binding using select /*+ no_index_join(t2) */ * from t1, t2, t3 where t1.a=t2.a and t3.b=t2.b`, - // `select * from t1, %st2, t3 where t1.a=t2.a and t3.b=t2.b`}, + {`create universal binding using select /*+ no_hash_join(t1) */ * from t1, t2 where t1.b=t2.b`, + `select * from %st1, t2 where t1.b=t2.b`}, + {`create universal binding using select /*+ no_hash_join(t2) */ * from t1, t2 where t1.c=t2.c`, + `select * from t1, %st2 where t1.c=t2.c`}, + {`create universal binding using select /*+ no_hash_join(t2) */ * from t1, t2, t3 where t1.a=t2.a and t3.b=t2.b`, + `select * from t1, %st2, t3 where t1.a=t2.a and t3.b=t2.b`}, + {`create universal binding using select /*+ no_merge_join(t1) */ * from t1, t2 where t1.b=t2.b`, + `select * from %st1, t2 where t1.b=t2.b`}, + {`create universal binding using select /*+ no_merge_join(t2) */ * from t1, t2 where t1.c=t2.c`, + `select * from t1, %st2 where t1.c=t2.c`}, + {`create universal binding using select /*+ no_merge_join(t2) */ * from t1, t2, t3 where t1.a=t2.a and t3.b=t2.b`, + `select * from t1, %st2, t3 where t1.a=t2.a and t3.b=t2.b`}, + {`create universal binding using select /*+ no_index_join(t1) */ * from t1, t2 where t1.b=t2.b`, + `select * from %st1, t2 where t1.b=t2.b`}, + {`create universal binding using select /*+ no_index_join(t2) */ * from t1, t2 where t1.c=t2.c`, + `select * from t1, %st2 where t1.c=t2.c`}, + {`create universal binding using select /*+ no_index_join(t2) */ * from t1, t2, t3 where t1.a=t2.a and t3.b=t2.b`, + `select * from t1, %st2, t3 where t1.a=t2.a and t3.b=t2.b`}, // join order hint {`create universal binding using select /*+ leading(t2) */ * from t1, t2 where t1.b=t2.b`, diff --git a/pkg/parser/ast/misc.go b/pkg/parser/ast/misc.go index bfc375b9a3..8e71de0f07 100644 --- a/pkg/parser/ast/misc.go +++ b/pkg/parser/ast/misc.go @@ -3670,9 +3670,11 @@ type HintTable struct { } func (ht *HintTable) Restore(ctx *format.RestoreCtx) { - if ht.DBName.L != "" { - ctx.WriteName(ht.DBName.String()) - ctx.WriteKeyWord(".") + if !ctx.Flags.HasWithoutSchemaNameFlag() { + if ht.DBName.L != "" { + ctx.WriteName(ht.DBName.String()) + ctx.WriteKeyWord(".") + } } ctx.WriteName(ht.TableName.String()) if ht.QBName.L != "" { @@ -3723,7 +3725,9 @@ func (n *TableOptimizerHint) Restore(ctx *format.RestoreCtx) error { ctx.WriteName(n.HintData.(string)) case "nth_plan": ctx.WritePlainf("%d", n.HintData.(int64)) - case "tidb_hj", "tidb_smj", "tidb_inlj", "hash_join", "hash_join_build", "hash_join_probe", "merge_join", "inl_join", "broadcast_join", "shuffle_join", "inl_hash_join", "inl_merge_join", "leading": + case "tidb_hj", "tidb_smj", "tidb_inlj", "hash_join", "hash_join_build", "hash_join_probe", "merge_join", "inl_join", + "broadcast_join", "shuffle_join", "inl_hash_join", "inl_merge_join", "leading", "no_hash_join", "no_merge_join", + "no_index_join", "no_index_hash_join", "no_index_merge_join": for i, table := range n.Tables { if i != 0 { ctx.WritePlain(", ")