diff --git a/executor/show.go b/executor/show.go index 2b5553bc16727..2897a0ffae0b9 100644 --- a/executor/show.go +++ b/executor/show.go @@ -274,7 +274,7 @@ func (e *ShowExec) fetchShowProcessList() error { if !hasProcessPriv && pi.User != loginUser.Username { continue } - row := pi.ToRow(e.Full) + row := pi.ToRowForShow(e.Full) e.appendRow(row) } return nil diff --git a/infoschema/tables.go b/infoschema/tables.go index b998c368e2300..71a2701577eb9 100644 --- a/infoschema/tables.go +++ b/infoschema/tables.go @@ -543,6 +543,7 @@ var tableProcesslistCols = []columnInfo{ {"TIME", mysql.TypeLong, 7, mysql.NotNullFlag, 0, nil}, {"STATE", mysql.TypeVarchar, 7, 0, nil, nil}, {"INFO", mysql.TypeString, 512, 0, nil, nil}, + {"MEM", mysql.TypeLonglong, 21, 0, nil, nil}, } var tableTiDBIndexesCols = []columnInfo{ @@ -862,7 +863,7 @@ func dataForProcesslist(ctx sessionctx.Context) [][]types.Datum { continue } - rows := pi.ToRow(true) + rows := pi.ToRow() record := types.MakeDatums(rows...) records = append(records, record) } diff --git a/infoschema/tables_test.go b/infoschema/tables_test.go index a92ca358d5c2f..1d5582421b867 100644 --- a/infoschema/tables_test.go +++ b/infoschema/tables_test.go @@ -131,6 +131,7 @@ func (s *testTableSuite) TestInfoschemaFieldValue(c *C) { User: "root", Host: "127.0.0.1", Command: mysql.ComQuery, + StmtCtx: tk.Se.GetSessionVars().StmtCtx, } tk.Se.SetSessionManager(sm) tk.MustQuery("SELECT user,host,command FROM information_schema.processlist;").Check(testkit.Rows("root 127.0.0.1 Query")) @@ -342,7 +343,9 @@ func (s *testTableSuite) TestSomeTables(c *C) { DB: "information_schema", Command: byte(1), State: 1, - Info: "do something"} + Info: "do something", + StmtCtx: tk.Se.GetSessionVars().StmtCtx, + } sm.processInfoMap[2] = &util.ProcessInfo{ ID: 2, User: "user-2", @@ -350,11 +353,25 @@ func (s *testTableSuite) TestSomeTables(c *C) { DB: "test", Command: byte(2), State: 2, - Info: "do something"} + Info: strings.Repeat("x", 101), + StmtCtx: tk.Se.GetSessionVars().StmtCtx, + } tk.Se.SetSessionManager(sm) - tk.MustQuery("select * from information_schema.PROCESSLIST order by ID;").Check( - testkit.Rows("1 user-1 localhost information_schema Quit 9223372036 1 do something", - "2 user-2 localhost test Init DB 9223372036 2 do something")) + tk.MustQuery("select * from information_schema.PROCESSLIST order by ID;").Sort().Check( + testkit.Rows( + fmt.Sprintf("1 user-1 localhost information_schema Quit 9223372036 1 %s 0", "do something"), + fmt.Sprintf("2 user-2 localhost test Init DB 9223372036 2 %s 0", strings.Repeat("x", 101)), + )) + tk.MustQuery("SHOW PROCESSLIST;").Sort().Check( + testkit.Rows( + fmt.Sprintf("1 user-1 localhost information_schema Quit 9223372036 1 %s", "do something"), + fmt.Sprintf("2 user-2 localhost test Init DB 9223372036 2 %s", strings.Repeat("x", 100)), + )) + tk.MustQuery("SHOW FULL PROCESSLIST;").Sort().Check( + testkit.Rows( + fmt.Sprintf("1 user-1 localhost information_schema Quit 9223372036 1 %s", "do something"), + fmt.Sprintf("2 user-2 localhost test Init DB 9223372036 2 %s", strings.Repeat("x", 101)), + )) sm = &mockSessionManager{make(map[uint64]*util.ProcessInfo, 2)} sm.processInfoMap[1] = &util.ProcessInfo{ @@ -380,8 +397,8 @@ func (s *testTableSuite) TestSomeTables(c *C) { tk.Se.SetSessionManager(sm) tk.MustQuery("select * from information_schema.PROCESSLIST order by ID;").Check( testkit.Rows( - fmt.Sprintf("1 user-1 localhost information_schema Quit 9223372036 1 %s", ""), - fmt.Sprintf("2 user-2 localhost Init DB 9223372036 2 %s", strings.Repeat("x", 101)), + fmt.Sprintf("1 user-1 localhost information_schema Quit 9223372036 1 %s 0", ""), + fmt.Sprintf("2 user-2 localhost Init DB 9223372036 2 %s 0", strings.Repeat("x", 101)), )) tk.MustQuery("SHOW PROCESSLIST;").Sort().Check( testkit.Rows( @@ -395,11 +412,11 @@ func (s *testTableSuite) TestSomeTables(c *C) { )) tk.MustQuery("select * from information_schema.PROCESSLIST where db is null;").Check( testkit.Rows( - fmt.Sprintf("2 user-2 localhost Init DB 9223372036 2 %s", strings.Repeat("x", 101)), + fmt.Sprintf("2 user-2 localhost Init DB 9223372036 2 %s 0", strings.Repeat("x", 101)), )) tk.MustQuery("select * from information_schema.PROCESSLIST where Info is null;").Check( testkit.Rows( - fmt.Sprintf("1 user-1 localhost information_schema Quit 9223372036 1 %s", ""), + fmt.Sprintf("1 user-1 localhost information_schema Quit 9223372036 1 %s 0", ""), )) } diff --git a/planner/core/logical_plans.go b/planner/core/logical_plans.go index 411937b4a315f..bc92c0241dcf6 100644 --- a/planner/core/logical_plans.go +++ b/planner/core/logical_plans.go @@ -322,7 +322,7 @@ type LogicalUnionScan struct { conditions []expression.Expression } -// DataSource represents a tablescan without condition push down. +// DataSource represents a tableScan without condition push down. type DataSource struct { logicalSchemaProducer diff --git a/session/session.go b/session/session.go index 8e00084fc1e4f..a68aa8ed4c131 100644 --- a/session/session.go +++ b/session/session.go @@ -98,7 +98,7 @@ var ( sessionExecuteParseDurationGeneral = metrics.SessionExecuteParseDuration.WithLabelValues(metrics.LblGeneral) ) -// Session context +// Session context, it is consistent with the lifecycle of a client connection. type Session interface { sessionctx.Context Status() uint16 // Flag of current status, such as autocommit. diff --git a/util/misc_test.go b/util/misc_test.go index 1ae47e6e2f6a7..7c365a98fdb5a 100644 --- a/util/misc_test.go +++ b/util/misc_test.go @@ -14,10 +14,17 @@ package util import ( + "bytes" "time" . "github.com/pingcap/check" "github.com/pingcap/errors" + "github.com/pingcap/parser" + "github.com/pingcap/parser/mysql" + "github.com/pingcap/parser/terror" + "github.com/pingcap/tidb/sessionctx/stmtctx" + "github.com/pingcap/tidb/util/memory" + "github.com/pingcap/tidb/util/stringutil" "github.com/pingcap/tidb/util/testleak" ) @@ -113,3 +120,65 @@ func (s *testMiscSuite) TestCompatibleParseGCTime(c *C) { c.Assert(err, NotNil) } } + +func (s *testMiscSuite) TestBasicFunc(c *C) { + // Test for GetStack. + b := GetStack() + c.Assert(len(b) < 4096, IsTrue) + + // Test for WithRecovery. + var recover interface{} + WithRecovery(func() { + panic("test") + }, func(r interface{}) { + recover = r + }) + c.Assert(recover, Equals, "test") + + // Test for SyntaxError. + c.Assert(SyntaxError(nil), IsNil) + c.Assert(terror.ErrorEqual(SyntaxError(errors.New("test")), parser.ErrParse), IsTrue) + c.Assert(terror.ErrorEqual(SyntaxError(parser.ErrSyntax.GenWithStackByArgs()), parser.ErrSyntax), IsTrue) + + // Test for SyntaxWarn. + c.Assert(SyntaxWarn(nil), IsNil) + c.Assert(terror.ErrorEqual(SyntaxWarn(errors.New("test")), parser.ErrParse), IsTrue) + + // Test for ProcessInfo. + pi := ProcessInfo{ + ID: 1, + User: "test", + Host: "www", + DB: "db", + Command: mysql.ComSleep, + Plan: nil, + Time: time.Now(), + State: 1, + Info: "test", + StmtCtx: &stmtctx.StatementContext{ + MemTracker: memory.NewTracker(stringutil.StringerStr(""), -1), + }, + } + row := pi.ToRowForShow(false) + row2 := pi.ToRowForShow(true) + c.Assert(row, DeepEquals, row2) + c.Assert(len(row), Equals, 8) + c.Assert(row[0], Equals, pi.ID) + c.Assert(row[1], Equals, pi.User) + c.Assert(row[2], Equals, pi.Host) + c.Assert(row[3], Equals, pi.DB) + c.Assert(row[4], Equals, "Sleep") + c.Assert(row[5], Equals, uint64(0)) + c.Assert(row[6], Equals, "1") + c.Assert(row[7], Equals, "test") + + row3 := pi.ToRow() + c.Assert(row3[:8], DeepEquals, row) + c.Assert(row3[8], Equals, int64(0)) + + // Test for RandomBuf. + buf := RandomBuf(5) + c.Assert(len(buf), Equals, 5) + c.Assert(bytes.Contains(buf, []byte("$")), IsFalse) + c.Assert(bytes.Contains(buf, []byte{0}), IsFalse) +} diff --git a/util/processinfo.go b/util/processinfo.go index 1fb103ac0e56b..b09edf810b184 100644 --- a/util/processinfo.go +++ b/util/processinfo.go @@ -41,8 +41,8 @@ type ProcessInfo struct { MaxExecutionTime uint64 } -// ToRow returns []interface{} for the row data of "show processlist" and "select * from infoschema.processlist". -func (pi *ProcessInfo) ToRow(full bool) []interface{} { +// ToRowForShow returns []interface{} for the row data of "SHOW [FULL] PROCESSLIST". +func (pi *ProcessInfo) ToRowForShow(full bool) []interface{} { var info interface{} if pi.Info != nil { if full { @@ -64,6 +64,12 @@ func (pi *ProcessInfo) ToRow(full bool) []interface{} { } } +// ToRow returns []interface{} for the row data of +// "SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST". +func (pi *ProcessInfo) ToRow() []interface{} { + return append(pi.ToRowForShow(true), pi.StmtCtx.MemTracker.BytesConsumed()) +} + // SessionManager is an interface for session manage. Show processlist and // kill statement rely on this interface. type SessionManager interface {