Search in sources :

Example 1 with TableRuleConfig

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

the class XMLSchemaLoader method loadTables.

private Map<String, TableConfig> loadTables(Element node) {
    Map<String, TableConfig> tables = new HashMap<String, TableConfig>();
    NodeList nodeList = node.getElementsByTagName("table");
    for (int i = 0; i < nodeList.getLength(); i++) {
        Element tableElement = (Element) nodeList.item(i);
        String name = tableElement.getAttribute("name").toUpperCase();
        String dataNode = tableElement.getAttribute("dataNode");
        TableRuleConfig tableRule = null;
        if (tableElement.hasAttribute("rule")) {
            String ruleName = tableElement.getAttribute("rule");
            tableRule = tableRules.get(ruleName);
            if (tableRule == null) {
                throw new ConfigException("rule " + ruleName + " is not found!");
            }
        }
        boolean ruleRequired = false;
        if (tableElement.hasAttribute("ruleRequired")) {
            ruleRequired = Boolean.parseBoolean(tableElement.getAttribute("ruleRequired"));
        }
        String[] tableNames = SplitUtil.split(name, ',', true);
        for (String tableName : tableNames) {
            TableConfig table = new TableConfig(tableName, dataNode, tableRule, ruleRequired);
            checkDataNodeExists(table.getDataNodes());
            if (tables.containsKey(table.getName())) {
                throw new ConfigException("table " + tableName + " duplicated!");
            }
            tables.put(table.getName(), table);
        }
    }
    return tables;
}
Also used : HashMap(java.util.HashMap) NodeList(org.w3c.dom.NodeList) Element(org.w3c.dom.Element) TableConfig(com.alibaba.cobar.config.model.TableConfig) ConfigException(com.alibaba.cobar.config.util.ConfigException) TableRuleConfig(com.alibaba.cobar.config.model.rule.TableRuleConfig)

Example 2 with TableRuleConfig

use of com.alibaba.cobar.config.model.rule.TableRuleConfig 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 3 with TableRuleConfig

use of com.alibaba.cobar.config.model.rule.TableRuleConfig 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 TableRuleConfig

use of com.alibaba.cobar.config.model.rule.TableRuleConfig 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

TableRuleConfig (com.alibaba.cobar.config.model.rule.TableRuleConfig)4 RuleConfig (com.alibaba.cobar.config.model.rule.RuleConfig)3 TableConfig (com.alibaba.cobar.config.model.TableConfig)2 ConfigException (com.alibaba.cobar.config.util.ConfigException)2 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 Element (org.w3c.dom.Element)2 NodeList (org.w3c.dom.NodeList)2 InExpressionList (com.alibaba.cobar.parser.ast.expression.misc.InExpressionList)1 SQLStatement (com.alibaba.cobar.parser.ast.stmt.SQLStatement)1 DMLInsertReplaceStatement (com.alibaba.cobar.parser.ast.stmt.dml.DMLInsertReplaceStatement)1 CobarHint (com.alibaba.cobar.route.hint.CobarHint)1 PartitionKeyVisitor (com.alibaba.cobar.route.visitor.PartitionKeyVisitor)1 HashSet (java.util.HashSet)1 LinkedList (java.util.LinkedList)1 List (java.util.List)1 Map (java.util.Map)1 Entry (java.util.Map.Entry)1 Node (org.w3c.dom.Node)1