Skip to content

Commit

Permalink
This is an automated cherry-pick of pingcap#46201
Browse files Browse the repository at this point in the history
Signed-off-by: ti-chi-bot <ti-community-prow-bot@tidb.io>
  • Loading branch information
time-and-fate authored and ti-chi-bot committed Aug 23, 2023
1 parent d927657 commit 19bd1da
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 4 deletions.
35 changes: 31 additions & 4 deletions executor/plan_replayer.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,23 @@ type PlanReplayerCaptureInfo struct {

// PlanReplayerDumpInfo indicates dump info
type PlanReplayerDumpInfo struct {
<<<<<<< HEAD
ExecStmts []ast.StmtNode
Analyze bool
Path string
File *os.File
FileName string
ctx sessionctx.Context
=======
ExecStmts []ast.StmtNode
Analyze bool
HistoricalStatsTS uint64
StartTS uint64
Path string
File *os.File
FileName string
ctx sessionctx.Context
>>>>>>> 9466e45f7d0 (executor: fix plan replayer for sql file input wrongly fetch startTS after `OnTxnEnd` (#46201))
}

// Next implements the Executor Next interface.
Expand All @@ -84,6 +95,15 @@ func (e *PlanReplayerExec) Next(ctx context.Context, req *chunk.Chunk) error {
if err != nil {
return err
}
// Note:
// For the dumping for SQL file case (len(e.DumpInfo.Path) > 0), the DumpInfo.dump() is called in
// handleFileTransInConn(), which is after TxnManager.OnTxnEnd(), where we can't access the TxnManager anymore.
// So we must fetch the startTS now.
startTS, err := sessiontxn.GetTxnManager(e.Ctx()).GetStmtReadTS()
if err != nil {
return err
}
e.DumpInfo.StartTS = startTS
if len(e.DumpInfo.Path) > 0 {
err = e.prepare()
if err != nil {
Expand Down Expand Up @@ -163,18 +183,25 @@ func (e *PlanReplayerExec) createFile() error {
func (e *PlanReplayerDumpInfo) dump(ctx context.Context) (err error) {
fileName := e.FileName
zf := e.File
startTS, err := sessiontxn.GetTxnManager(e.ctx).GetStmtReadTS()
if err != nil {
return err
}
task := &domain.PlanReplayerDumpTask{
<<<<<<< HEAD
StartTS: startTS,
FileName: fileName,
Zf: zf,
SessionVars: e.ctx.GetSessionVars(),
TblStats: nil,
ExecStmts: e.ExecStmts,
Analyze: e.Analyze,
=======
StartTS: e.StartTS,
FileName: fileName,
Zf: zf,
SessionVars: e.ctx.GetSessionVars(),
TblStats: nil,
ExecStmts: e.ExecStmts,
Analyze: e.Analyze,
HistoricalStatsTS: e.HistoricalStatsTS,
>>>>>>> 9466e45f7d0 (executor: fix plan replayer for sql file input wrongly fetch startTS after `OnTxnEnd` (#46201))
}
err = domain.DumpPlanReplayerInfo(ctx, e.ctx, task)
if err != nil {
Expand Down
4 changes: 4 additions & 0 deletions server/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,11 @@ go_test(
data = glob(["testdata/**"]),
embed = [":server"],
flaky = True,
<<<<<<< HEAD
shard_count = 50,
=======
shard_count = 47,
>>>>>>> 9466e45f7d0 (executor: fix plan replayer for sql file input wrongly fetch startTS after `OnTxnEnd` (#46201))
deps = [
"//config",
"//ddl",
Expand Down
53 changes: 53 additions & 0 deletions server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,17 @@ import (
"github.com/go-sql-driver/mysql"
"github.com/pingcap/errors"
"github.com/pingcap/failpoint"
<<<<<<< HEAD
"github.com/pingcap/log"
"github.com/pingcap/tidb/errno"
"github.com/pingcap/tidb/kv"
tmysql "github.com/pingcap/tidb/parser/mysql"
=======
"github.com/pingcap/tidb/parser/mysql"
"github.com/pingcap/tidb/server/internal"
"github.com/pingcap/tidb/server/internal/testutil"
"github.com/pingcap/tidb/server/internal/util"
>>>>>>> 9466e45f7d0 (executor: fix plan replayer for sql file input wrongly fetch startTS after `OnTxnEnd` (#46201))
"github.com/pingcap/tidb/testkit"
"github.com/pingcap/tidb/testkit/testenv"
"github.com/pingcap/tidb/util/versioninfo"
Expand Down Expand Up @@ -69,6 +76,7 @@ func newTestServerClient() *testServerClient {
}
}

<<<<<<< HEAD
// statusURL return the full URL of a status path
func (cli *testServerClient) statusURL(path string) string {
return fmt.Sprintf("%s://localhost:%d%s", cli.statusScheme, cli.statusPort, path)
Expand Down Expand Up @@ -2450,4 +2458,49 @@ func (cli *testServerClient) runTestInfoschemaClientErrors(t *testing.T) {
}
}
})
=======
func TestIssue46197(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tidbdrv := NewTiDBDriver(store)
cfg := util.NewTestConfig()
cfg.Port, cfg.Status.StatusPort = 0, 0
cfg.Status.ReportStatus = false
server, err := NewServer(cfg, tidbdrv)
require.NoError(t, err)
defer server.Close()

// Mock the content of the SQL file in PacketIO buffer.
// First 4 bytes are the header, followed by the actual content.
// This acts like we are sending "select * from t1;" from the client when tidb requests the "a.txt" file.
var inBuffer bytes.Buffer
_, err = inBuffer.Write([]byte{0x11, 0x00, 0x00, 0x01})
require.NoError(t, err)
_, err = inBuffer.Write([]byte("select * from t1;"))
require.NoError(t, err)

// clientConn setup
brc := util.NewBufferedReadConn(&testutil.BytesConn{Buffer: inBuffer})
pkt := internal.NewPacketIO(brc)
pkt.SetBufWriter(bufio.NewWriter(bytes.NewBuffer(nil)))
cc := &clientConn{
server: server,
alloc: arena.NewAllocator(1024),
chunkAlloc: chunk.NewAllocator(),
pkt: pkt,
capability: mysql.ClientLocalFiles,
}
ctx := context.Background()
cc.SetCtx(&TiDBContext{Session: tk.Session(), stmts: make(map[int]*TiDBStatement)})

tk.MustExec("use test")
tk.MustExec("create table t1 (a int, b int)")

// 3 is mysql.ComQuery, followed by the SQL text.
require.NoError(t, cc.dispatch(ctx, []byte("\u0003plan replayer dump explain 'a.txt'")))

// clean up
path := testdata.ConvertRowsToStrings(tk.MustQuery("select @@tidb_last_plan_replayer_token").Rows())
require.NoError(t, os.Remove(filepath.Join(replayer.GetPlanReplayerDirName(), path[0])))
>>>>>>> 9466e45f7d0 (executor: fix plan replayer for sql file input wrongly fetch startTS after `OnTxnEnd` (#46201))
}

0 comments on commit 19bd1da

Please sign in to comment.