diff --git a/infoschema/cluster_tables_test.go b/infoschema/cluster_tables_test.go index 5e323b2adc88a..bbd85f1be657d 100644 --- a/infoschema/cluster_tables_test.go +++ b/infoschema/cluster_tables_test.go @@ -852,3 +852,37 @@ func TestMDLView(t *testing.T) { wg.Wait() } + +func TestCreateBindingForPrepareToken(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(a int, b time, c varchar(5))") + + //some builtin functions listed in https://dev.mysql.com/doc/refman/8.0/en/function-resolution.html + cases := []string{ + "select std(a) from t", + "select cast(a as decimal(10, 2)) from t", + "select bit_or(a) from t", + "select min(a) from t", + "select max(a) from t", + "select substr(c, 1, 2) from t", + } + + for _, sql := range cases { + prep := fmt.Sprintf("prepare stmt from '%s'", sql) + tk.MustExec(prep) + tk.MustExec("execute stmt") + 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 binding from history using plan digest '%s'", planDigest[0][0])) + } +} diff --git a/util/stmtsummary/statement_summary.go b/util/stmtsummary/statement_summary.go index 4db62bdb7c048..cf03f78009e92 100644 --- a/util/stmtsummary/statement_summary.go +++ b/util/stmtsummary/statement_summary.go @@ -516,10 +516,17 @@ func getBindableStmtByPlanDigest(ssbd *stmtSummaryByDigest, planDigest string) * Collation: ssElement.collation, Users: ssElement.authUsers, } - // If it is SQL command prepare / execute, the ssElement.sampleSQL is `execute ...`, we should get the original select query. + // If it is SQL command prepare / execute, we should remove the arguments // If it is binary protocol prepare / execute, ssbd.normalizedSQL should be same as ssElement.sampleSQL. +<<<<<<< HEAD if ssElement.prepared { stmt.Query = ssbd.normalizedSQL +======= + if row.GetInt64(4) == 1 { + if idx := strings.LastIndex(stmt.Query, "[arguments:"); idx != -1 { + stmt.Query = stmt.Query[:idx] + } +>>>>>>> 98fe813b49 (planner: fix space requirement when binding from history (#41140)) } return stmt }