Search in sources :

Example 1 with TableConfig

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

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

use of com.alibaba.cobar.config.model.TableConfig in project cobar by alibaba.

the class XMLSchemaLoader method loadSchemas.

private void loadSchemas(Element root) {
    NodeList list = root.getElementsByTagName("schema");
    for (int i = 0, n = list.getLength(); i < n; i++) {
        Element schemaElement = (Element) list.item(i);
        String name = schemaElement.getAttribute("name");
        String dataNode = schemaElement.getAttribute("dataNode");
        // 在非空的情况下检查dataNode是否存在
        if (dataNode != null && dataNode.length() != 0) {
            checkDataNodeExists(dataNode);
        } else {
            // 确保非空
            dataNode = "";
        }
        String group = "default";
        if (schemaElement.hasAttribute("group")) {
            group = schemaElement.getAttribute("group").trim();
        }
        Map<String, TableConfig> tables = loadTables(schemaElement);
        if (schemas.containsKey(name)) {
            throw new ConfigException("schema " + name + " duplicated!");
        }
        boolean keepSqlSchema = false;
        if (schemaElement.hasAttribute("keepSqlSchema")) {
            keepSqlSchema = Boolean.parseBoolean(schemaElement.getAttribute("keepSqlSchema").trim());
        }
        schemas.put(name, new SchemaConfig(name, dataNode, group, keepSqlSchema, tables));
    }
}
Also used : SchemaConfig(com.alibaba.cobar.config.model.SchemaConfig) NodeList(org.w3c.dom.NodeList) Element(org.w3c.dom.Element) TableConfig(com.alibaba.cobar.config.model.TableConfig) ConfigException(com.alibaba.cobar.config.util.ConfigException)

Aggregations

TableConfig (com.alibaba.cobar.config.model.TableConfig)3 TableRuleConfig (com.alibaba.cobar.config.model.rule.TableRuleConfig)2 ConfigException (com.alibaba.cobar.config.util.ConfigException)2 HashMap (java.util.HashMap)2 Element (org.w3c.dom.Element)2 NodeList (org.w3c.dom.NodeList)2 SchemaConfig (com.alibaba.cobar.config.model.SchemaConfig)1 RuleConfig (com.alibaba.cobar.config.model.rule.RuleConfig)1 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 ArrayList (java.util.ArrayList)1 LinkedList (java.util.LinkedList)1 List (java.util.List)1 Map (java.util.Map)1 Entry (java.util.Map.Entry)1