Search in sources :

Example 1 with RuleConfig

use of io.mycat.config.model.rule.RuleConfig in project Mycat-Server by MyCATApache.

the class XMLSchemaLoader method loadTables.

private Map<String, TableConfig> loadTables(Element node) {
    // Map<String, TableConfig> tables = new HashMap<String, TableConfig>();
    // 支持表名中包含引号[`] BEN GONG
    Map<String, TableConfig> tables = new TableConfigMap();
    NodeList nodeList = node.getElementsByTagName("table");
    for (int i = 0; i < nodeList.getLength(); i++) {
        Element tableElement = (Element) nodeList.item(i);
        String tableNameElement = tableElement.getAttribute("name").toUpperCase();
        //TODO:路由, 增加对动态日期表的支持
        String tableNameSuffixElement = tableElement.getAttribute("nameSuffix").toUpperCase();
        if (!"".equals(tableNameSuffixElement)) {
            if (tableNameElement.split(",").length > 1) {
                throw new ConfigException("nameSuffix " + tableNameSuffixElement + ", require name parameter cannot multiple breaks!");
            }
            //前缀用来标明日期格式
            tableNameElement = doTableNameSuffix(tableNameElement, tableNameSuffixElement);
        }
        //记录主键,用于之后路由分析,以及启用自增长主键
        String[] tableNames = tableNameElement.split(",");
        String primaryKey = tableElement.hasAttribute("primaryKey") ? tableElement.getAttribute("primaryKey").toUpperCase() : null;
        //记录是否主键自增,默认不是,(启用全局sequence handler)
        boolean autoIncrement = false;
        if (tableElement.hasAttribute("autoIncrement")) {
            autoIncrement = Boolean.parseBoolean(tableElement.getAttribute("autoIncrement"));
        }
        //记录是否需要加返回结果集限制,默认需要加
        boolean needAddLimit = true;
        if (tableElement.hasAttribute("needAddLimit")) {
            needAddLimit = Boolean.parseBoolean(tableElement.getAttribute("needAddLimit"));
        }
        //记录type,是否为global
        String tableTypeStr = tableElement.hasAttribute("type") ? tableElement.getAttribute("type") : null;
        int tableType = TableConfig.TYPE_GLOBAL_DEFAULT;
        if ("global".equalsIgnoreCase(tableTypeStr)) {
            tableType = TableConfig.TYPE_GLOBAL_TABLE;
        }
        //记录dataNode,就是分布在哪些dataNode上
        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"));
        }
        if (tableNames == null) {
            throw new ConfigException("table name is not found!");
        }
        //distribute函数,重新编排dataNode
        String distPrex = "distribute(";
        boolean distTableDns = dataNode.startsWith(distPrex);
        if (distTableDns) {
            dataNode = dataNode.substring(distPrex.length(), dataNode.length() - 1);
        }
        //分表功能
        String subTables = tableElement.getAttribute("subTables");
        for (int j = 0; j < tableNames.length; j++) {
            String tableName = tableNames[j];
            TableRuleConfig tableRuleConfig = tableRule;
            if (tableRuleConfig != null) {
                //对于实现TableRuleAware的function进行特殊处理  根据每个表新建个实例
                RuleConfig rule = tableRuleConfig.getRule();
                if (rule.getRuleAlgorithm() instanceof TableRuleAware) {
                    tableRuleConfig = (TableRuleConfig) ObjectUtil.copyObject(tableRuleConfig);
                    tableRules.remove(tableRuleConfig.getName());
                    String newRuleName = tableRuleConfig.getName() + "_" + tableName;
                    tableRuleConfig.setName(newRuleName);
                    TableRuleAware tableRuleAware = (TableRuleAware) tableRuleConfig.getRule().getRuleAlgorithm();
                    tableRuleAware.setRuleName(newRuleName);
                    tableRuleAware.setTableName(tableName);
                    tableRuleConfig.getRule().getRuleAlgorithm().init();
                    tableRules.put(newRuleName, tableRuleConfig);
                }
            }
            TableConfig table = new TableConfig(tableName, primaryKey, autoIncrement, needAddLimit, tableType, dataNode, getDbType(dataNode), (tableRuleConfig != null) ? tableRuleConfig.getRule() : null, ruleRequired, null, false, null, null, subTables);
            checkDataNodeExists(table.getDataNodes());
            // 检查分片表分片规则配置是否合法
            if (table.getRule() != null) {
                checkRuleSuitTable(table);
            }
            if (distTableDns) {
                distributeDataNodes(table.getDataNodes());
            }
            //检查去重
            if (tables.containsKey(table.getName())) {
                throw new ConfigException("table " + tableName + " duplicated!");
            }
            //放入map
            tables.put(table.getName(), table);
        }
        //只有tableName配置的是单个表(没有逗号)的时候才能有子表
        if (tableNames.length == 1) {
            TableConfig table = tables.get(tableNames[0]);
            // process child tables
            processChildTables(tables, table, dataNode, tableElement);
        }
    }
    return tables;
}
Also used : NodeList(org.w3c.dom.NodeList) Element(org.w3c.dom.Element) TableRuleAware(io.mycat.route.function.TableRuleAware) ConfigException(io.mycat.config.util.ConfigException) TableConfigMap(io.mycat.config.model.TableConfigMap) TableRuleConfig(io.mycat.config.model.rule.TableRuleConfig) TableConfig(io.mycat.config.model.TableConfig) TableRuleConfig(io.mycat.config.model.rule.TableRuleConfig) RuleConfig(io.mycat.config.model.rule.RuleConfig)

Example 2 with RuleConfig

use of io.mycat.config.model.rule.RuleConfig in project Mycat-Server by MyCATApache.

the class XMLRuleLoader method loadRule.

private RuleConfig loadRule(Element element) throws SQLSyntaxErrorException {
    //读取columns
    Element columnsEle = ConfigUtil.loadElement(element, "columns");
    String column = columnsEle.getTextContent();
    String[] columns = SplitUtil.split(column, ',', true);
    if (columns.length > 1) {
        throw new ConfigException("table rule coulmns has multi values:" + columnsEle.getTextContent());
    }
    //读取algorithm
    Element algorithmEle = ConfigUtil.loadElement(element, "algorithm");
    String algorithm = algorithmEle.getTextContent();
    return new RuleConfig(column.toUpperCase(), algorithm);
}
Also used : Element(org.w3c.dom.Element) ConfigException(io.mycat.config.util.ConfigException) TableRuleConfig(io.mycat.config.model.rule.TableRuleConfig) RuleConfig(io.mycat.config.model.rule.RuleConfig)

Example 3 with RuleConfig

use of io.mycat.config.model.rule.RuleConfig in project Mycat-Server by MyCATApache.

the class SwitchCommitListener method modifyRuleData.

private CuratorTransactionFinal modifyRuleData(CuratorTransactionFinal transactionFinal, List<MigrateTask> allTaskList, TableConfig tableConfig, List<String> allNewDataNodes) throws Exception {
    InterProcessMutex ruleDataLock = null;
    try {
        String path = ZKUtils.getZKBasePath() + "lock/ruledata.lock";
        ruleDataLock = new InterProcessMutex(ZKUtils.getConnection(), path);
        ruleDataLock.acquire(30, TimeUnit.SECONDS);
        RuleConfig ruleConfig = tableConfig.getRule();
        String ruleName = ((TableRuleAware) ruleConfig.getRuleAlgorithm()).getRuleName() + ".properties";
        String rulePath = ZKUtils.getZKBasePath() + "ruledata/" + ruleName;
        CuratorFramework zk = ZKUtils.getConnection();
        byte[] ruleData = zk.getData().forPath(rulePath);
        Properties prop = new Properties();
        prop.load(new ByteArrayInputStream(ruleData));
        for (MigrateTask migrateTask : allTaskList) {
            modifyRuleData(prop, migrateTask, allNewDataNodes);
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        prop.store(out, "WARNING   !!!Please do not modify or delete this file!!!");
        if (transactionFinal == null) {
            transactionFinal = ZKUtils.getConnection().inTransaction().setData().forPath(rulePath, out.toByteArray()).and();
        } else {
            transactionFinal.setData().forPath(rulePath, out.toByteArray());
        }
    } finally {
        try {
            if (ruleDataLock != null)
                ruleDataLock.release();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    return transactionFinal;
}
Also used : CuratorFramework(org.apache.curator.framework.CuratorFramework) ByteArrayInputStream(java.io.ByteArrayInputStream) RuleConfig(io.mycat.config.model.rule.RuleConfig) ByteArrayOutputStream(java.io.ByteArrayOutputStream) InterProcessMutex(org.apache.curator.framework.recipes.locks.InterProcessMutex) SQLException(java.sql.SQLException) IOException(java.io.IOException)

Example 4 with RuleConfig

use of io.mycat.config.model.rule.RuleConfig in project Mycat-Server by MyCATApache.

the class DruidMycatRouteStrategy method routeNormalSqlWithAST.

@Override
public RouteResultset routeNormalSqlWithAST(SchemaConfig schema, String stmt, RouteResultset rrs, String charset, LayerCachePool cachePool) throws SQLNonTransientException {
    /**
		 *  只有mysql时只支持mysql语法
		 */
    SQLStatementParser parser = null;
    if (schema.isNeedSupportMultiDBType()) {
        parser = new MycatStatementParser(stmt);
    } else {
        parser = new MySqlStatementParser(stmt);
    }
    MycatSchemaStatVisitor visitor = null;
    SQLStatement statement;
    /**
		 * 解析出现问题统一抛SQL语法错误
		 */
    try {
        statement = parser.parseStatement();
        visitor = new MycatSchemaStatVisitor();
    } catch (Exception t) {
        LOGGER.error("DruidMycatRouteStrategyError", t);
        throw new SQLSyntaxErrorException(t);
    }
    /**
		 * 检验unsupported statement
		 */
    checkUnSupportedStatement(statement);
    DruidParser druidParser = DruidParserFactory.create(schema, statement, visitor);
    druidParser.parser(schema, rrs, statement, stmt, cachePool, visitor);
    DruidShardingParseInfo ctx = druidParser.getCtx();
    rrs.setTables(ctx.getTables());
    /**
		 * DruidParser 解析过程中已完成了路由的直接返回
		 */
    if (rrs.isFinishedRoute()) {
        return rrs;
    }
    /**
		 * 没有from的select语句或其他
		 */
    if ((ctx.getTables() == null || ctx.getTables().size() == 0) && (ctx.getTableAliasMap() == null || ctx.getTableAliasMap().isEmpty())) {
        return RouterUtil.routeToSingleNode(rrs, schema.getRandomDataNode(), druidParser.getCtx().getSql());
    }
    if (druidParser.getCtx().getRouteCalculateUnits().size() == 0) {
        RouteCalculateUnit routeCalculateUnit = new RouteCalculateUnit();
        druidParser.getCtx().addRouteCalculateUnit(routeCalculateUnit);
    }
    SortedSet<RouteResultsetNode> nodeSet = new TreeSet<RouteResultsetNode>();
    for (RouteCalculateUnit unit : druidParser.getCtx().getRouteCalculateUnits()) {
        RouteResultset rrsTmp = RouterUtil.tryRouteForTables(schema, druidParser.getCtx(), unit, rrs, isSelect(statement), cachePool);
        if (rrsTmp != null) {
            for (RouteResultsetNode node : rrsTmp.getNodes()) {
                nodeSet.add(node);
            }
        }
    }
    RouteResultsetNode[] nodes = new RouteResultsetNode[nodeSet.size()];
    int i = 0;
    for (RouteResultsetNode aNodeSet : nodeSet) {
        nodes[i] = aNodeSet;
        if (statement instanceof MySqlInsertStatement && ctx.getTables().size() == 1 && schema.getTables().containsKey(ctx.getTables().get(0))) {
            RuleConfig rule = schema.getTables().get(ctx.getTables().get(0)).getRule();
            if (rule != null && rule.getRuleAlgorithm() instanceof SlotFunction) {
                aNodeSet.setStatement(ParseUtil.changeInsertAddSlot(aNodeSet.getStatement(), aNodeSet.getSlot()));
            }
        }
        i++;
    }
    rrs.setNodes(nodes);
    /**
		 *  subTables="t_order$1-2,t_order3"
		 *目前分表 1.6 开始支持 幵丏 dataNode 在分表条件下只能配置一个,分表条件下不支持join。
		 */
    if (rrs.isDistTable()) {
        return this.routeDisTable(statement, rrs);
    }
    return rrs;
}
Also used : DruidShardingParseInfo(io.mycat.route.parser.druid.DruidShardingParseInfo) RouteCalculateUnit(io.mycat.route.parser.druid.RouteCalculateUnit) SQLStatementParser(com.alibaba.druid.sql.parser.SQLStatementParser) MycatStatementParser(io.mycat.route.parser.druid.MycatStatementParser) MycatSchemaStatVisitor(io.mycat.route.parser.druid.MycatSchemaStatVisitor) SQLSyntaxErrorException(java.sql.SQLSyntaxErrorException) MySqlInsertStatement(com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement) SQLStatement(com.alibaba.druid.sql.ast.SQLStatement) SQLNonTransientException(java.sql.SQLNonTransientException) SQLSyntaxErrorException(java.sql.SQLSyntaxErrorException) SlotFunction(io.mycat.route.function.SlotFunction) DruidParser(io.mycat.route.parser.druid.DruidParser) TreeSet(java.util.TreeSet) RouteResultsetNode(io.mycat.route.RouteResultsetNode) RuleConfig(io.mycat.config.model.rule.RuleConfig) MySqlStatementParser(com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser) RouteResultset(io.mycat.route.RouteResultset)

Example 5 with RuleConfig

use of io.mycat.config.model.rule.RuleConfig in project Mycat-Server by MyCATApache.

the class ConfigComparer method loadMigratorTable.

private void loadMigratorTable(TableConfig oldTable, TableConfig newTable, String schemaName, String tableName) {
    //禁止配置非拆分表
    if (oldTable == null || newTable == null) {
        throw new ConfigException("please check tableFile.properties,make sure " + schemaName + ":" + tableName + " is sharding table ");
    }
    //忽略全局表
    if (oldTable.isGlobalTable() || newTable.isGlobalTable()) {
        String message = "global table: " + schemaName + ":" + tableName + " is ignore!";
        System.out.println("Warn: " + message);
        LOGGER.warn(message);
    } else {
        List<DataNode> oldDN = getDataNodes(oldTable, oldDataNodes, oldDataHosts);
        List<DataNode> newDN = getDataNodes(newTable, newDataNodes, newDataHosts);
        //忽略数据节点分布没有发生变化的表
        if (isNeedMigrate(oldDN, newDN)) {
            checkRuleConfig(oldTable.getRule(), newTable.getRule(), schemaName, tableName);
            RuleConfig newRC = newTable.getRule();
            TableMigrateInfo tmi = new TableMigrateInfo(schemaName, tableName, oldDN, newDN, newRC.getRuleAlgorithm(), newRC.getColumn());
            migratorTables.add(tmi);
        } else {
            String message = schemaName + ":" + tableName + " is ignore,no need to migrate!";
            LOGGER.warn(message);
            System.out.println("Warn: " + message);
        }
    }
}
Also used : ConfigException(io.mycat.config.util.ConfigException) RuleConfig(io.mycat.config.model.rule.RuleConfig)

Aggregations

RuleConfig (io.mycat.config.model.rule.RuleConfig)13 TableConfig (io.mycat.config.model.TableConfig)7 Test (org.junit.Test)5 ConfigException (io.mycat.config.util.ConfigException)4 TableRuleConfig (io.mycat.config.model.rule.TableRuleConfig)3 AbstractPartitionAlgorithm (io.mycat.route.function.AbstractPartitionAlgorithm)3 Element (org.w3c.dom.Element)3 SlotFunction (io.mycat.route.function.SlotFunction)2 NodeList (org.w3c.dom.NodeList)2 SQLStatement (com.alibaba.druid.sql.ast.SQLStatement)1 MySqlInsertStatement (com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement)1 MySqlStatementParser (com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser)1 SQLStatementParser (com.alibaba.druid.sql.parser.SQLStatementParser)1 SchemaConfig (io.mycat.config.model.SchemaConfig)1 TableConfigMap (io.mycat.config.model.TableConfigMap)1 RouteResultset (io.mycat.route.RouteResultset)1 RouteResultsetNode (io.mycat.route.RouteResultsetNode)1 ReloadFunction (io.mycat.route.function.ReloadFunction)1 TableRuleAware (io.mycat.route.function.TableRuleAware)1 DruidParser (io.mycat.route.parser.druid.DruidParser)1