TiDB source code reading (2) MySQL protocol in TiDB

TiDB source code reading (2) MySQL protocol in TiDB

When SQL came here through the path described in the previous article, the dispatch function, like its name, case different types of SQL statements into different functions, then let's take a look at this function, here:

server/conn.go

The process is roughly as follows

t := time.Now() 

Record the timestamp t, which is approximately the timestamp when the SQL starts to execute.

cc.lastPacket = data
cmd := data[0]
data = data[1:]
dataStr := string(hack.String(data)) 


TiDB also needs to parse according to this format, data[0] is the first byte of data, and the rest are commands.

Command list of MySQL request message

0x00 COM_SLEEP  
0x01 COM_QUIT  
0x02 COM_INIT_DB  
0x03 COM_QUERY SQL 
0x04 COM_FIELD_LIST  
0x05 COM_CREATE_DB  
0x06 COM_DROP_DB  
0x07 COM_REFRESH  
0x08 COM_SHUTDOWN  
0x09 COM_STATISTICS  
0x0A COM_PROCESS_INFO  
0x0B COM_CONNECT  
0x0C COM_PROCESS_KILL  
0x0D COM_DEBUG  
0x0E COM_PING  
0x0F COM_TIME  
0x10 COM_DELAYED_INSERT  
0x11 COM_CHANGE_USER  
0x12 COM_BINLOG_DUMP  
0x13 COM_TABLE_DUMP  
0x14 COM_CONNECT_OUT  
0x15 COM_REGISTER_SLAVE  
0x16 COM_STMT_PREPARE  SQL 
0x17 COM_STMT_EXECUTE  
0x18 COM_STMT_SEND_LONG_DATA  BLOB 
0x19 COM_STMT_CLOSE  
0x1A COM_STMT_RESET  
0x1B COM_SET_OPTION  
0x1C COM_STMT_FETCH   

Let's take a look at the next part of dispatch, which is part of the MySQL protocol currently implemented by TiDB.

switch cmd {
	case mysql.ComPing, 
             mysql.ComStmtClose, 
             mysql.ComStmtSendLongData, 
             mysql.ComStmtReset,
	     mysql.ComSetOption, 
             mysql.ComChangeUser:
		cc.ctx.SetProcessInfo("", t, cmd, 0)
	case mysql.ComInitDB:
		cc.ctx.SetProcessInfo("use "+dataStr, t, cmd, 0)
	}
switch cmd {
	case mysql.ComSleep:
	case mysql.ComQuit:
	case mysql.ComQuery:
	case mysql.ComPing:
	case mysql.ComInitDB:
	case mysql.ComFieldList:
	case mysql.ComStmtPrepare:
	case mysql.ComStmtExecute:
	case mysql.ComStmtFetch:
	case mysql.ComStmtClose:
	case mysql.ComStmtSendLongData:
	case mysql.ComStmtReset:
	case mysql.ComSetOption:
	case mysql.ComChangeUser
	default://other not support 

Let's try a few examples through debug

create database


use database


create table


update


delete


After that, I tried drop table and drop database again, the same is cmd=3, case=ComQuery.

use database is special, divided into a cmd=3 and 2 process. Explain that first query the database, and then use.

Looking back at the dispatch part of the code, to simplify the process is to walk twice:

1 
switch cmd {//3
       case mysql.ComQuery://select database()
2 
switch cmd {//mysql.ComInitDB = 2
       case mysql.ComInitDB
       cc.ctx.SetProcessInfo("use "+ dataStr, t, cmd, 0)// use 

So here is to query databases through select database() first, and then assemble use to only use databases.

In short, I have tried show create table, commit, rollback, begin, prepare, show variables like and so on.

But... it's all ComQuery. So we learned that most of TiDB is ComQuery. Even so, different SQL must be parsed and executed through different types.

case mysql.ComQuery: 
	if len(data) > 0 && data[len(data)-1] == 0 {
		data = data[:len(data)-1]
		dataStr = string(hack.String(data))
	}
	return cc.handleQuery(ctx, dataStr) 

So let s take a closer look at this case, and look at cc.handleQuery(ctx, dataStr) 

func (cc *clientConn) handleQuery(ctx context.Context, sql string) (err error) {
	stmts, err := cc.ctx.Parse(ctx, sql)
} 

To sum it up, look at Parse, how to do parsing.

This time go to 

github.com/pingcap/parser@v0.0.0-20200623082809-b74301ac298b/parser.y 

You will see that there are many cases here


According to different SQL, execute different parser.y

These will also be introduced in future pages.