diff --git a/mysql/const.go b/mysql/const.go index 3bc12e84..735d3ce4 100644 --- a/mysql/const.go +++ b/mysql/const.go @@ -173,6 +173,7 @@ var ( TK_ID_SELECT = 11 TK_ID_START = 12 TK_ID_TRANSACTION = 13 + TK_ID_SHOW = 14 PARSE_TOKEN_MAP = map[string]int{ "insert": TK_ID_INSERT, @@ -188,6 +189,7 @@ var ( "use": TK_ID_USE, "start": TK_ID_START, "transaction": TK_ID_TRANSACTION, + "show": TK_ID_SHOW, } // '/' COMMENT_PREFIX uint8 = 47 diff --git a/proxy/server/conn.go b/proxy/server/conn.go index 0f9cc6e9..ebea15a8 100644 --- a/proxy/server/conn.go +++ b/proxy/server/conn.go @@ -252,10 +252,7 @@ func (c *ClientConn) readHandshakeResponse() error { //if connect without database, use default db db = c.proxy.schema.db } - - if err := c.useDB(db); err != nil { - return err - } + c.db = db return nil } @@ -317,11 +314,7 @@ func (c *ClientConn) dispatch(data []byte) error { case mysql.COM_PING: return c.writeOK(nil) case mysql.COM_INIT_DB: - if err := c.useDB(hack.String(data)); err != nil { - return err - } else { - return c.writeOK(nil) - } + return c.handleUseDB(hack.String(data)) case mysql.COM_FIELD_LIST: return c.handleFieldList(data) case mysql.COM_STMT_PREPARE: @@ -345,27 +338,6 @@ func (c *ClientConn) dispatch(data []byte) error { return nil } -func (c *ClientConn) useDB(db string) error { - if c.schema == nil { - return mysql.NewDefaultError(mysql.ER_NO_DB_ERROR) - } - - nodeName := c.schema.rule.DefaultRule.Nodes[0] - - n := c.proxy.GetNode(nodeName) - co, err := n.GetMasterConn() - defer c.closeConn(co, false) - if err != nil { - return err - } - - if err = co.UseDB(db); err != nil { - return err - } - c.db = db - return nil -} - func (c *ClientConn) writeOK(r *mysql.Result) error { if r == nil { r = &mysql.Result{Status: c.status} diff --git a/proxy/server/conn_preshard.go b/proxy/server/conn_preshard.go index 1289422a..776a68ff 100644 --- a/proxy/server/conn_preshard.go +++ b/proxy/server/conn_preshard.go @@ -127,6 +127,9 @@ func (c *ClientConn) GetTransExecDB(tokens []string, sql string) (*ExecuteDB, er tokensLen := len(tokens) executeDB := new(ExecuteDB) + //transaction execute in master db + executeDB.IsSlave = false + if 2 <= tokensLen { if tokens[0][0] == mysql.COMMENT_PREFIX { nodeName := strings.Trim(tokens[0], mysql.COMMENT_STRING) @@ -144,8 +147,6 @@ func (c *ClientConn) GetTransExecDB(tokens []string, sql string) (*ExecuteDB, er if executeDB == nil { return nil, nil } - //transaction execute in master db - executeDB.IsSlave = false return executeDB, nil } if len(c.txConns) == 1 && c.txConns[executeDB.ExecNode] == nil { @@ -171,6 +172,8 @@ func (c *ClientConn) GetExecDB(tokens []string, sql string) (*ExecuteDB, error) return c.getUpdateExecDB(tokens, tokensLen) case mysql.TK_ID_SET: return c.getSetExecDB(tokens, tokensLen, sql) + case mysql.TK_ID_SHOW: + return c.getShowExecDB(tokens, tokensLen) default: return nil, nil } @@ -359,3 +362,17 @@ func (c *ClientConn) getSetExecDB(tokens []string, tokensLen int, sql string) (* return executeDB, nil } + +//get the execute database for show sql +//choose slave preferentially +func (c *ClientConn) getShowExecDB(tokens []string, tokensLen int) (*ExecuteDB, error) { + executeDB := new(ExecuteDB) + executeDB.IsSlave = true + + err := c.setExecuteNode(tokens, tokensLen, executeDB) + if err != nil { + return nil, err + } + + return executeDB, nil +} diff --git a/proxy/server/conn_query.go b/proxy/server/conn_query.go index 7000de23..cf00d56f 100644 --- a/proxy/server/conn_query.go +++ b/proxy/server/conn_query.go @@ -93,7 +93,7 @@ func (c *ClientConn) handleQuery(sql string) (err error) { case *sqlparser.AdminHelp: return c.handleAdminHelp(v) case *sqlparser.UseDB: - return c.handleUseDB(v) + return c.handleUseDB(v.DB) case *sqlparser.SimpleSelect: return c.handleSimpleSelect(v) default: diff --git a/proxy/server/conn_use.go b/proxy/server/conn_use.go index 14885720..5b709f29 100644 --- a/proxy/server/conn_use.go +++ b/proxy/server/conn_use.go @@ -17,13 +17,16 @@ package server import ( "fmt" + "github.com/flike/kingshard/backend" "github.com/flike/kingshard/mysql" - "github.com/flike/kingshard/sqlparser" ) -func (c *ClientConn) handleUseDB(stmt *sqlparser.UseDB) error { - if len(stmt.DB) == 0 { - return fmt.Errorf("must have database, not %s", sqlparser.String(stmt)) +func (c *ClientConn) handleUseDB(dbName string) error { + var co *backend.BackendConn + var err error + + if len(dbName) == 0 { + return fmt.Errorf("must have database, the length of dbName is zero") } if c.schema == nil { return mysql.NewDefaultError(mysql.ER_NO_DB_ERROR) @@ -32,15 +35,19 @@ func (c *ClientConn) handleUseDB(stmt *sqlparser.UseDB) error { nodeName := c.schema.rule.DefaultRule.Nodes[0] n := c.proxy.GetNode(nodeName) - co, err := n.GetMasterConn() + //get the connection from slave preferentially + co, err = n.GetSlaveConn() + if err != nil { + co, err = n.GetMasterConn() + } defer c.closeConn(co, false) if err != nil { return err } - if err = co.UseDB(string(stmt.DB)); err != nil { + if err = co.UseDB(dbName); err != nil { return err } - c.db = string(stmt.DB) + c.db = dbName return c.writeOK(nil) }