Search in sources :

Example 1 with RuleConfig

use of com.alibaba.cobar.config.model.rule.RuleConfig in project cobar by alibaba.

the class ServerRouter method route.

public static RouteResultset route(SchemaConfig schema, String stmt, String charset, Object info) throws SQLNonTransientException {
    RouteResultset rrs = new RouteResultset(stmt);
    // 检查是否含有cobar hint
    int prefixIndex = HintRouter.indexOfPrefix(stmt);
    if (prefixIndex >= 0) {
        HintRouter.routeFromHint(info, schema, rrs, prefixIndex, stmt);
        return rrs;
    }
    // 检查schema是否含有拆分库
    if (schema.isNoSharding()) {
        if (schema.isKeepSqlSchema()) {
            SQLStatement ast = SQLParserDelegate.parse(stmt, charset == null ? MySQLParser.DEFAULT_CHARSET : charset);
            PartitionKeyVisitor visitor = new PartitionKeyVisitor(schema.getTables());
            visitor.setTrimSchema(schema.getName());
            ast.accept(visitor);
            if (visitor.isSchemaTrimmed()) {
                stmt = genSQL(ast, stmt);
            }
        }
        RouteResultsetNode[] nodes = new RouteResultsetNode[1];
        nodes[0] = new RouteResultsetNode(schema.getDataNode(), stmt);
        rrs.setNodes(nodes);
        return rrs;
    }
    // 生成和展开AST
    SQLStatement ast = SQLParserDelegate.parse(stmt, charset == null ? MySQLParser.DEFAULT_CHARSET : charset);
    PartitionKeyVisitor visitor = new PartitionKeyVisitor(schema.getTables());
    visitor.setTrimSchema(schema.isKeepSqlSchema() ? schema.getName() : null);
    ast.accept(visitor);
    // 如果sql包含用户自定义的schema,则路由到default节点
    if (schema.isKeepSqlSchema() && visitor.isCustomedSchema()) {
        if (visitor.isSchemaTrimmed()) {
            stmt = genSQL(ast, stmt);
        }
        RouteResultsetNode[] nodes = new RouteResultsetNode[1];
        nodes[0] = new RouteResultsetNode(schema.getDataNode(), stmt);
        rrs.setNodes(nodes);
        return rrs;
    }
    // 元数据语句路由
    if (visitor.isTableMetaRead()) {
        MetaRouter.routeForTableMeta(rrs, schema, ast, visitor, stmt);
        if (visitor.isNeedRewriteField()) {
            rrs.setFlag(RouteResultset.REWRITE_FIELD);
        }
        return rrs;
    }
    // 匹配规则
    TableConfig matchedTable = null;
    RuleConfig rule = null;
    Map<String, List<Object>> columnValues = null;
    Map<String, Map<String, List<Object>>> astExt = visitor.getColumnValue();
    Map<String, TableConfig> tables = schema.getTables();
    ft: for (Entry<String, Map<String, List<Object>>> e : astExt.entrySet()) {
        Map<String, List<Object>> col2Val = e.getValue();
        TableConfig tc = tables.get(e.getKey());
        if (tc == null) {
            continue;
        }
        if (matchedTable == null) {
            matchedTable = tc;
        }
        if (col2Val == null || col2Val.isEmpty()) {
            continue;
        }
        TableRuleConfig tr = tc.getRule();
        if (tr != null) {
            for (RuleConfig rc : tr.getRules()) {
                boolean match = true;
                for (String ruleColumn : rc.getColumns()) {
                    match &= col2Val.containsKey(ruleColumn);
                }
                if (match) {
                    columnValues = col2Val;
                    rule = rc;
                    matchedTable = tc;
                    break ft;
                }
            }
        }
    }
    // 规则匹配处理,表级别和列级别。
    if (matchedTable == null) {
        String sql = visitor.isSchemaTrimmed() ? genSQL(ast, stmt) : stmt;
        RouteResultsetNode[] rn = new RouteResultsetNode[1];
        if ("".equals(schema.getDataNode()) && isSystemReadSQL(ast)) {
            rn[0] = new RouteResultsetNode(schema.getRandomDataNode(), sql);
        } else {
            rn[0] = new RouteResultsetNode(schema.getDataNode(), sql);
        }
        rrs.setNodes(rn);
        return rrs;
    }
    if (rule == null) {
        if (matchedTable.isRuleRequired()) {
            throw new IllegalArgumentException("route rule for table " + matchedTable.getName() + " is required: " + stmt);
        }
        String[] dataNodes = matchedTable.getDataNodes();
        String sql = visitor.isSchemaTrimmed() ? genSQL(ast, stmt) : stmt;
        RouteResultsetNode[] rn = new RouteResultsetNode[dataNodes.length];
        for (int i = 0; i < dataNodes.length; ++i) {
            rn[i] = new RouteResultsetNode(dataNodes[i], sql);
        }
        rrs.setNodes(rn);
        setGroupFlagAndLimit(rrs, visitor);
        return rrs;
    }
    // 规则计算
    validateAST(ast, matchedTable, rule, visitor);
    Map<Integer, List<Object[]>> dnMap = ruleCalculate(matchedTable, rule, columnValues);
    if (dnMap == null || dnMap.isEmpty()) {
        throw new IllegalArgumentException("No target dataNode for rule " + rule);
    }
    // 判断路由结果是单库还是多库
    if (dnMap.size() == 1) {
        String dataNode = matchedTable.getDataNodes()[dnMap.keySet().iterator().next()];
        String sql = visitor.isSchemaTrimmed() ? genSQL(ast, stmt) : stmt;
        RouteResultsetNode[] rn = new RouteResultsetNode[1];
        rn[0] = new RouteResultsetNode(dataNode, sql);
        rrs.setNodes(rn);
    } else {
        RouteResultsetNode[] rn = new RouteResultsetNode[dnMap.size()];
        if (ast instanceof DMLInsertReplaceStatement) {
            DMLInsertReplaceStatement ir = (DMLInsertReplaceStatement) ast;
            dispatchInsertReplace(rn, ir, rule.getColumns(), dnMap, matchedTable, stmt, visitor);
        } else {
            dispatchWhereBasedStmt(rn, ast, rule.getColumns(), dnMap, matchedTable, stmt, visitor);
        }
        rrs.setNodes(rn);
        setGroupFlagAndLimit(rrs, visitor);
    }
    return rrs;
}
Also used : SQLStatement(com.alibaba.cobar.parser.ast.stmt.SQLStatement) CobarHint(com.alibaba.cobar.route.hint.CobarHint) TableRuleConfig(com.alibaba.cobar.config.model.rule.TableRuleConfig) DMLInsertReplaceStatement(com.alibaba.cobar.parser.ast.stmt.dml.DMLInsertReplaceStatement) Entry(java.util.Map.Entry) TableConfig(com.alibaba.cobar.config.model.TableConfig) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) List(java.util.List) InExpressionList(com.alibaba.cobar.parser.ast.expression.misc.InExpressionList) TableRuleConfig(com.alibaba.cobar.config.model.rule.TableRuleConfig) RuleConfig(com.alibaba.cobar.config.model.rule.RuleConfig) HashMap(java.util.HashMap) Map(java.util.Map) PartitionKeyVisitor(com.alibaba.cobar.route.visitor.PartitionKeyVisitor)

Example 2 with RuleConfig

use of com.alibaba.cobar.config.model.rule.RuleConfig in project cobar by alibaba.

the class RouteRuleInitializer method initRouteRule.

public static void initRouteRule(SchemaLoader loader) throws SQLSyntaxErrorException {
    Map<String, RuleAlgorithm> functions = loader.getFunctions();
    MySQLFunctionManager functionManager = new MySQLFunctionManager(true);
    buildFuncManager(functionManager, functions);
    for (RuleConfig conf : loader.listRuleConfig()) {
        String algorithmString = conf.getAlgorithm();
        MySQLLexer lexer = new MySQLLexer(algorithmString);
        MySQLExprParser parser = new MySQLExprParser(lexer, functionManager, false, MySQLParser.DEFAULT_CHARSET);
        Expression expression = parser.expression();
        if (lexer.token() != MySQLToken.EOF) {
            throw new ConfigException("route algorithm not end with EOF: " + algorithmString);
        }
        RuleAlgorithm algorithm;
        if (expression instanceof RuleAlgorithm) {
            algorithm = (RuleAlgorithm) expression;
        } else {
            algorithm = new ExpressionAdapter(expression);
        }
        conf.setRuleAlgorithm(algorithm);
    }
}
Also used : MySQLLexer(com.alibaba.cobar.parser.recognizer.mysql.lexer.MySQLLexer) RuleAlgorithm(com.alibaba.cobar.config.model.rule.RuleAlgorithm) MySQLExprParser(com.alibaba.cobar.parser.recognizer.mysql.syntax.MySQLExprParser) FunctionExpression(com.alibaba.cobar.parser.ast.expression.primary.function.FunctionExpression) Expression(com.alibaba.cobar.parser.ast.expression.Expression) MySQLFunctionManager(com.alibaba.cobar.parser.recognizer.mysql.MySQLFunctionManager) ConfigException(com.alibaba.cobar.config.util.ConfigException) RuleConfig(com.alibaba.cobar.config.model.rule.RuleConfig) ExpressionAdapter(com.alibaba.cobar.route.function.ExpressionAdapter)

Example 3 with RuleConfig

use of com.alibaba.cobar.config.model.rule.RuleConfig in project cobar by alibaba.

the class TableConfig method buildColumnIndex.

private static Set<String> buildColumnIndex(TableRuleConfig rule) {
    if (rule == null) {
        return Collections.emptySet();
    }
    List<RuleConfig> rs = rule.getRules();
    if (rs == null || rs.isEmpty()) {
        return Collections.emptySet();
    }
    Set<String> columnIndex = new HashSet<String>();
    for (RuleConfig r : rs) {
        List<String> columns = r.getColumns();
        if (columns != null) {
            for (String col : columns) {
                if (col != null) {
                    columnIndex.add(col.toUpperCase());
                }
            }
        }
    }
    return columnIndex;
}
Also used : RuleConfig(com.alibaba.cobar.config.model.rule.RuleConfig) TableRuleConfig(com.alibaba.cobar.config.model.rule.TableRuleConfig) HashSet(java.util.HashSet)

Example 4 with RuleConfig

use of com.alibaba.cobar.config.model.rule.RuleConfig in project cobar by alibaba.

the class XMLRuleLoader method loadRule.

private RuleConfig loadRule(Element element) throws SQLSyntaxErrorException {
    Element columnsEle = ConfigUtil.loadElement(element, "columns");
    String[] columns = SplitUtil.split(columnsEle.getTextContent(), ',', true);
    for (int i = 0; i < columns.length; ++i) {
        columns[i] = columns[i].toUpperCase();
    }
    Element algorithmEle = ConfigUtil.loadElement(element, "algorithm");
    String algorithm = algorithmEle.getTextContent();
    return new RuleConfig(columns, algorithm);
}
Also used : Element(org.w3c.dom.Element) TableRuleConfig(com.alibaba.cobar.config.model.rule.TableRuleConfig) RuleConfig(com.alibaba.cobar.config.model.rule.RuleConfig)

Example 5 with RuleConfig

use of com.alibaba.cobar.config.model.rule.RuleConfig in project cobar by alibaba.

the class XMLRuleLoader method loadTableRules.

private void loadTableRules(Element root) throws SQLSyntaxErrorException {
    NodeList list = root.getElementsByTagName("tableRule");
    for (int i = 0, n = list.getLength(); i < n; ++i) {
        Node node = list.item(i);
        if (node instanceof Element) {
            Element e = (Element) node;
            String name = e.getAttribute("name");
            if (tableRules.containsKey(name)) {
                throw new ConfigException("table rule " + name + " duplicated!");
            }
            NodeList ruleNodes = e.getElementsByTagName("rule");
            int length = ruleNodes.getLength();
            List<RuleConfig> ruleList = new ArrayList<RuleConfig>(length);
            for (int j = 0; j < length; ++j) {
                RuleConfig rule = loadRule((Element) ruleNodes.item(j));
                ruleList.add(rule);
                rules.add(rule);
            }
            tableRules.put(name, new TableRuleConfig(name, ruleList));
        }
    }
}
Also used : NodeList(org.w3c.dom.NodeList) Node(org.w3c.dom.Node) Element(org.w3c.dom.Element) ArrayList(java.util.ArrayList) ConfigException(com.alibaba.cobar.config.util.ConfigException) TableRuleConfig(com.alibaba.cobar.config.model.rule.TableRuleConfig) RuleConfig(com.alibaba.cobar.config.model.rule.RuleConfig) TableRuleConfig(com.alibaba.cobar.config.model.rule.TableRuleConfig)

Aggregations

RuleConfig (com.alibaba.cobar.config.model.rule.RuleConfig)5 TableRuleConfig (com.alibaba.cobar.config.model.rule.TableRuleConfig)4 ConfigException (com.alibaba.cobar.config.util.ConfigException)2 ArrayList (java.util.ArrayList)2 Element (org.w3c.dom.Element)2 TableConfig (com.alibaba.cobar.config.model.TableConfig)1 RuleAlgorithm (com.alibaba.cobar.config.model.rule.RuleAlgorithm)1 Expression (com.alibaba.cobar.parser.ast.expression.Expression)1 InExpressionList (com.alibaba.cobar.parser.ast.expression.misc.InExpressionList)1 FunctionExpression (com.alibaba.cobar.parser.ast.expression.primary.function.FunctionExpression)1 SQLStatement (com.alibaba.cobar.parser.ast.stmt.SQLStatement)1 DMLInsertReplaceStatement (com.alibaba.cobar.parser.ast.stmt.dml.DMLInsertReplaceStatement)1 MySQLFunctionManager (com.alibaba.cobar.parser.recognizer.mysql.MySQLFunctionManager)1 MySQLLexer (com.alibaba.cobar.parser.recognizer.mysql.lexer.MySQLLexer)1 MySQLExprParser (com.alibaba.cobar.parser.recognizer.mysql.syntax.MySQLExprParser)1 ExpressionAdapter (com.alibaba.cobar.route.function.ExpressionAdapter)1 CobarHint (com.alibaba.cobar.route.hint.CobarHint)1 PartitionKeyVisitor (com.alibaba.cobar.route.visitor.PartitionKeyVisitor)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1