//get the execute database for delete sql func (c *ClientConn) getDeleteExecDB(tokens []string, tokensLen int) (*ExecuteDB, error) { executeDB := new(ExecuteDB) schema := c.proxy.schema rules := schema.rule.Rules if len(rules) != 0 { for i := 1; i < tokensLen; i++ { if strings.ToLower(tokens[i]) == mysql.TK_STR_FROM { if i+1 < tokensLen { tableName := sqlparser.GetTableName(tokens[i+1]) if _, ok := rules[tableName]; ok { return nil, nil } } } } } err := c.setExecuteNode(tokens, tokensLen, executeDB) if err != nil { return nil, err } return executeDB, nil }
//get the execute database for select sql func (c *ClientConn) getSelectExecDB(tokens []string, tokensLen int) (*ExecuteDB, error) { executeDB := new(ExecuteDB) schema := c.proxy.schema rules := schema.rule.Rules executeDB.IsSlave = true if len(rules) != 0 { for i := 1; i < tokensLen; i++ { if strings.ToLower(tokens[i]) == mysql.TK_STR_FROM { if i+1 < tokensLen { tableName := sqlparser.GetTableName(tokens[i+1]) if _, ok := rules[tableName]; ok { return nil, nil } else { //if the table is not shard table,send the sql //to default db break } } } if strings.ToLower(tokens[i]) == mysql.TK_STR_LAST_INSERT_ID { return nil, nil } } } err := c.setExecuteNode(tokens, tokensLen, executeDB) if err != nil { return nil, err } return executeDB, nil }
func (c *ClientConn) GetExecNode(tokens []string, sql string) (*backend.Node, bool, error) { var execNode *backend.Node var fromSlave bool schema := c.proxy.schemas[c.proxy.db] rules := schema.rule.Rules if 0 < len(rules) { tokensLen := len(tokens) if 0 < tokensLen { tokenId, ok := mysql.WHITE_TOKEN_MAP[strings.ToLower(tokens[0])] if ok == true { switch tokenId { case mysql.TK_ID_SELECT, mysql.TK_ID_DELETE: for i := 1; i < tokensLen; i++ { if strings.ToLower(tokens[i]) == mysql.TK_STR_FROM { if i+1 < tokensLen { tableName := sqlparser.GetTableName(tokens[i+1]) if _, ok := rules[tableName]; ok { return nil, false, nil } } } } case mysql.TK_ID_INSERT, mysql.TK_ID_REPLACE: for i := 0; i < tokensLen; i++ { if strings.ToLower(tokens[i]) == mysql.TK_STR_INTO { if i+1 < tokensLen { tableName := sqlparser.GetTableName(tokens[i+1]) if _, ok := rules[tableName]; ok { return nil, false, nil } } } } case mysql.TK_ID_UPDATE: for i := 0; i < tokensLen; i++ { if strings.ToLower(tokens[i]) == mysql.TK_STR_SET { tableName := sqlparser.GetTableName(tokens[i-1]) if _, ok := rules[tableName]; ok { return nil, false, nil } } } default: return nil, false, nil } } } //get node if 2 <= tokensLen { if tokens[0][0] == mysql.COMMENT_PREFIX { nodeName := strings.Trim(tokens[0], mysql.COMMENT_STRING) if c.schema.nodes[nodeName] != nil { execNode = c.schema.nodes[nodeName] } //select if mysql.WHITE_TOKEN_MAP[tokens[1]] == mysql.TK_ID_SELECT { fromSlave = true } } } } if execNode == nil { defaultRule := c.schema.rule.DefaultRule if len(defaultRule.Nodes) == 0 { return nil, false, errors.ErrNoDefaultNode } execNode = c.proxy.GetNode(defaultRule.Nodes[0]) } return execNode, fromSlave, nil }
func (c *ClientConn) GetExecNode(tokens []string, sql string) (*backend.Node, bool, error) { var execNode *backend.Node var fromSlave bool schema := c.proxy.schema rules := schema.rule.Rules tokensLen := len(tokens) if 0 < tokensLen { tokenId, ok := mysql.PARSE_TOKEN_MAP[strings.ToLower(tokens[0])] if ok == true { switch tokenId { case mysql.TK_ID_SELECT, mysql.TK_ID_DELETE: if len(rules) == 0 { if tokenId == mysql.TK_ID_SELECT { fromSlave = true } break } for i := 1; i < tokensLen; i++ { if strings.ToLower(tokens[i]) == mysql.TK_STR_FROM { if i+1 < tokensLen { tableName := sqlparser.GetTableName(tokens[i+1]) if _, ok := rules[tableName]; ok { return nil, false, nil } else { if tokenId == mysql.TK_ID_SELECT { fromSlave = true } } } } } case mysql.TK_ID_INSERT, mysql.TK_ID_REPLACE: if len(rules) == 0 { break } for i := 0; i < tokensLen; i++ { if strings.ToLower(tokens[i]) == mysql.TK_STR_INTO { if i+1 < tokensLen { tableName := sqlparser.GetInsertTableName(tokens[i+1]) if _, ok := rules[tableName]; ok { return nil, false, nil } } } } case mysql.TK_ID_UPDATE: if len(rules) == 0 { break } for i := 0; i < tokensLen; i++ { if strings.ToLower(tokens[i]) == mysql.TK_STR_SET { tableName := sqlparser.GetTableName(tokens[i-1]) if _, ok := rules[tableName]; ok { return nil, false, nil } } } case mysql.TK_ID_SET: if len(tokens) < 2 { break } tmp1 := strings.Split(sql, "=") tmp2 := strings.Split(tmp1[0], " ") secondWord := strings.ToLower(tmp2[1]) if secondWord == mysql.TK_STR_NAMES || secondWord == mysql.TK_STR_RESULTS || secondWord == mysql.TK_STR_CLIENT || secondWord == mysql.TK_STR_CONNECTION || secondWord == mysql.TK_STR_AUTOCOMMIT { return nil, false, nil } default: return nil, false, nil } } } //get node if 2 <= tokensLen { if tokens[0][0] == mysql.COMMENT_PREFIX { nodeName := strings.Trim(tokens[0], mysql.COMMENT_STRING) if c.schema.nodes[nodeName] != nil { execNode = c.schema.nodes[nodeName] } //select if mysql.PARSE_TOKEN_MAP[tokens[1]] == mysql.TK_ID_SELECT { fromSlave = true } } } if execNode == nil { defaultRule := c.schema.rule.DefaultRule if len(defaultRule.Nodes) == 0 { return nil, false, errors.ErrNoDefaultNode } execNode = c.proxy.GetNode(defaultRule.Nodes[0]) } return execNode, fromSlave, nil }