Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

planner: supply more test for binding from history #40242

Merged
merged 8 commits into from
Jan 3, 2023
Merged
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 188 additions & 0 deletions infoschema/cluster_tables_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1054,3 +1054,191 @@ func TestSetBindingStatusBySQLDigest(t *testing.T) {
tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1"))
tk.MustGetErrMsg("set binding enabled for sql digest '2'", "can't find any binding for '2'")
}

func TestCreateBindingWhenCloseStmtSummaryTable(t *testing.T) {
s := new(clusterTablesSuite)
s.store, s.dom = testkit.CreateMockStoreAndDomain(t)
s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0", nil)
s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer()
s.startTime = time.Now()
defer s.httpServer.Close()
defer s.rpcserver.Stop()
tk := s.newTestKitWithRoot(t)
require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil))

tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(id int primary key, a int, key(a))")
tk.MustExec("set global tidb_enable_stmt_summary = 0")
tk.MustExec("select /*+ ignore_index(t, a) */ * from t where a = 1")

tk.MustGetErrMsg("create binding from history using plan digest '4e3159169cc63c14b139a4e7d72eae1759875c9a9581f94bb2079aae961189cb'",
"can't find any plans for '4e3159169cc63c14b139a4e7d72eae1759875c9a9581f94bb2079aae961189cb'")
}

func TestCreateBindingForNotSupportedStmt(t *testing.T) {
s := new(clusterTablesSuite)
s.store, s.dom = testkit.CreateMockStoreAndDomain(t)
s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0", nil)
s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer()
s.startTime = time.Now()
defer s.httpServer.Close()
defer s.rpcserver.Stop()
tk := s.newTestKitWithRoot(t)
require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil))

tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(id int primary key, a int, key(a))")

sql := "admin show ddl jobs"
tk.MustExec(sql)
planDigest := tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", sql)).Rows()
tk.MustGetErrMsg(fmt.Sprintf("create session binding from history using plan digest '%s'", planDigest[0][0]), fmt.Sprintf("can't find any plans for '%s'", planDigest[0][0]))

sql = "show tables"
tk.MustExec(sql)
planDigest = tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", sql)).Rows()
tk.MustGetErrMsg(fmt.Sprintf("create session binding from history using plan digest '%s'", planDigest[0][0]), fmt.Sprintf("can't find any plans for '%s'", planDigest[0][0]))

sql = "explain select /*+ ignore_index(t, a) */ * from t where a = 1"
tk.MustExec(sql)
planDigest = tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", sql)).Rows()
tk.MustGetErrMsg(fmt.Sprintf("create session binding from history using plan digest '%s'", planDigest[0][0]), fmt.Sprintf("can't find any plans for '%s'", planDigest[0][0]))
}

func TestCreateBindingRepeatedly(t *testing.T) {
s := new(clusterTablesSuite)
s.store, s.dom = testkit.CreateMockStoreAndDomain(t)
s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0", nil)
s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer()
s.startTime = time.Now()
defer s.httpServer.Close()
defer s.rpcserver.Stop()
tk := s.newTestKitWithRoot(t)
require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil))

tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(id int primary key, a int, key(a))")

sql := "select /*+ ignore_index(t, a) */ * from t where a = 1"
tk.MustExec(sql)
planDigest := tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", sql)).Rows()
tk.MustExec(fmt.Sprintf("create session binding from history using plan digest '%s'", planDigest[0][0]))
binding := tk.MustQuery("show bindings").Rows()
loc, _ := time.LoadLocation("Asia/Shanghai")
createTime, _ := time.ParseInLocation("2006-01-02 15:04:05", binding[0][4].(string), loc)
updateTime, _ := time.ParseInLocation("2006-01-02 15:04:05", binding[0][5].(string), loc)

// binding from history cover binding from history
tk.MustExec(fmt.Sprintf("create session binding from history using plan digest '%s'", planDigest[0][0]))
tk.MustExec(fmt.Sprintf("create session binding from history using plan digest '%s'", planDigest[0][0]))
tk.MustExec(fmt.Sprintf("create session binding from history using plan digest '%s'", planDigest[0][0]))
binding1 := tk.MustQuery("show bindings").Rows()
createTime1, _ := time.ParseInLocation("2006-01-02 15:04:05", binding1[0][4].(string), loc)
updateTime1, _ := time.ParseInLocation("2006-01-02 15:04:05", binding1[0][5].(string), loc)
require.Greater(t, createTime1.UnixNano(), createTime.UnixNano())
require.Greater(t, updateTime1.UnixNano(), updateTime.UnixNano())
for i := range binding1[0] {
if i != 4 && i != 5 {
require.Equal(t, binding[0][i], binding1[0][i])
}
}
// binding from sql cover binding from history
tk.MustExec("create binding for select * from t where a = 1 using select /*+ ignore_index(t, a) */ * from t where a = 1")
binding2 := tk.MustQuery("show bindings").Rows()
createTime2, _ := time.ParseInLocation("2006-01-02 15:04:05", binding2[0][4].(string), loc)
updateTime2, _ := time.ParseInLocation("2006-01-02 15:04:05", binding2[0][5].(string), loc)
require.Greater(t, createTime2.UnixNano(), createTime1.UnixNano())
require.Greater(t, updateTime2.UnixNano(), updateTime1.UnixNano())
require.Equal(t, binding2[0][8], "manual")
require.Equal(t, binding2[0][10], "")
for i := range binding2[0] {
if i != 1 && i != 4 && i != 5 && i != 8 && i != 10 {
// bind_sql, create_time, update_time, source, plan_digest may be different
require.Equal(t, binding1[0][i], binding2[0][i])
}
}
// binding from history cover binding from sql
tk.MustExec(fmt.Sprintf("create session binding from history using plan digest '%s'", planDigest[0][0]))
binding3 := tk.MustQuery("show bindings").Rows()
createTime3, _ := time.ParseInLocation("2006-01-02 15:04:05", binding3[0][4].(string), loc)
updateTime3, _ := time.ParseInLocation("2006-01-02 15:04:05", binding3[0][5].(string), loc)
require.Greater(t, createTime3.UnixNano(), createTime2.UnixNano())
require.Greater(t, updateTime3.UnixNano(), updateTime2.UnixNano())
require.Equal(t, binding3[0][8], "history")
require.Equal(t, binding3[0][10], planDigest[0][0])
for i := range binding3[0] {
if i != 1 && i != 4 && i != 5 && i != 8 && i != 10 {
// bind_sql, create_time, update_time, source, plan_digest may be different
require.Equal(t, binding2[0][i], binding3[0][i])
}
}
}

func TestCreateBindingWithUsingKeyword(t *testing.T) {
s := new(clusterTablesSuite)
s.store, s.dom = testkit.CreateMockStoreAndDomain(t)
s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0", nil)
s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer()
s.startTime = time.Now()
defer s.httpServer.Close()
defer s.rpcserver.Stop()
tk := s.newTestKitWithRoot(t)
require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil))

tk.MustExec("use test")
tk.MustExec("drop table if exists t, t1, t2")
tk.MustExec("create table t(id int primary key, a int, key(a))")
tk.MustExec("create table t1(id int primary key, a int, key(a))")
tk.MustExec("create table t2(id int primary key, a int, key(a))")

// `JOIN` keyword and not specifying the associated columns with the `USING` keyword.
tk.MustGetErrMsg("CREATE GLOBAL BINDING for SELECT * FROM t t1 JOIN t t2 USING SELECT * FROM t t1 JOIN t t2;",
"[parser:1064]You have an error in your SQL syntax; check the manual that corresponds to your TiDB version for the right syntax to use line 1 column 67 near \"SELECT * FROM t t1 JOIN t t2;\" ")
sql := "SELECT * FROM t t1 JOIN t t2;"
tk.MustExec(sql)
planDigest := tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", sql)).Rows()
tk.MustExec(fmt.Sprintf("create session binding from history using plan digest '%s'", planDigest[0][0]))
tk.MustExec(sql)
tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1"))

// `DELETE` statements that contain the `USING` keyword.
tk.MustGetErrMsg("`CREATE GLOBAL BINDING for DELETE FROM t1 USING t1 JOIN t2 ON t1.a = t2.a USING DELETE FROM t1 USING t1 JOIN t2 ON t1.a = t2.a;",
"[parser:1064]You have an error in your SQL syntax; check the manual that corresponds to your TiDB version for the right syntax to use line 1 column 127 near \"`CREATE GLOBAL BINDING for DELETE FROM t1 USING t1 JOIN t2 ON t1.a = t2.a USING DELETE FROM t1 USING t1 JOIN t2 ON t1.a = t2.a;\" ")
sql = "DELETE FROM t1 USING t1 JOIN t2 ON t1.a = t2.a;"
tk.MustExec(sql)
planDigest = tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", sql)).Rows()
tk.MustExec(fmt.Sprintf("create session binding from history using plan digest '%s'", planDigest[0][0]))
tk.MustExec(sql)
tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1"))
}

func TestNewCreatedBindingCanWorkWithPlanCache(t *testing.T) {
s := new(clusterTablesSuite)
s.store, s.dom = testkit.CreateMockStoreAndDomain(t)
s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0", nil)
s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer()
s.startTime = time.Now()
defer s.httpServer.Close()
defer s.rpcserver.Stop()
tk := s.newTestKitWithRoot(t)
require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil))

tk.MustExec("use test")
tk.MustExec("drop table if exists t, t1, t2")
tk.MustExec("create table t(id int primary key, a int, key(a))")

tk.MustExec("prepare stmt from 'select * from t where a = ?'")
tk.MustExec("set @a = 0")
tk.MustExec("execute stmt using @a")
tk.MustExec("execute stmt using @a")
tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1"))
sql := "select /*+ ignore_index(t, a) */ * from t where a = 1"
tk.MustExec(sql)
planDigest := tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", sql)).Rows()
tk.MustExec(fmt.Sprintf("create session binding from history using plan digest '%s'", planDigest[0][0]))
tk.MustExec("execute stmt using @a")
tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1"))
}