Пример #1
0
//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
}
Пример #2
0
//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
}
Пример #3
0
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
}
Пример #4
0
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
}