Search in sources :

Example 51 with TableConfig

use of io.mycat.config.model.TableConfig in project Mycat_plus by coderczp.

the class DruidInsertParser method parserBatchInsert.

/**
 * insert into .... select .... 或insert into table() values (),(),....
 * @param schema
 * @param rrs
 * @param insertStmt
 * @throws SQLNonTransientException
 */
private void parserBatchInsert(SchemaConfig schema, RouteResultset rrs, String partitionColumn, String tableName, MySqlInsertStatement insertStmt) throws SQLNonTransientException {
    // insert into table() values (),(),....
    if (insertStmt.getValuesList().size() > 1) {
        // 字段列数
        int columnNum = insertStmt.getColumns().size();
        int shardingColIndex = getShardingColIndex(insertStmt, partitionColumn);
        if (shardingColIndex == -1) {
            String msg = "bad insert sql (sharding column:" + partitionColumn + " not provided," + insertStmt;
            LOGGER.warn(msg);
            throw new SQLNonTransientException(msg);
        } else {
            List<ValuesClause> valueClauseList = insertStmt.getValuesList();
            Map<Integer, List<ValuesClause>> nodeValuesMap = new HashMap<Integer, List<ValuesClause>>();
            Map<Integer, Integer> slotsMap = new HashMap<>();
            TableConfig tableConfig = schema.getTables().get(tableName);
            AbstractPartitionAlgorithm algorithm = tableConfig.getRule().getRuleAlgorithm();
            for (ValuesClause valueClause : valueClauseList) {
                if (valueClause.getValues().size() != columnNum) {
                    String msg = "bad insert sql columnSize != valueSize:" + columnNum + " != " + valueClause.getValues().size() + "values:" + valueClause;
                    LOGGER.warn(msg);
                    throw new SQLNonTransientException(msg);
                }
                SQLExpr expr = valueClause.getValues().get(shardingColIndex);
                String shardingValue = null;
                if (expr instanceof SQLIntegerExpr) {
                    SQLIntegerExpr intExpr = (SQLIntegerExpr) expr;
                    shardingValue = intExpr.getNumber() + "";
                } else if (expr instanceof SQLCharExpr) {
                    SQLCharExpr charExpr = (SQLCharExpr) expr;
                    shardingValue = charExpr.getText();
                }
                Integer nodeIndex = algorithm.calculate(shardingValue);
                if (algorithm instanceof SlotFunction) {
                    slotsMap.put(nodeIndex, ((SlotFunction) algorithm).slotValue());
                }
                // 没找到插入的分片
                if (nodeIndex == null) {
                    String msg = "can't find any valid datanode :" + tableName + " -> " + partitionColumn + " -> " + shardingValue;
                    LOGGER.warn(msg);
                    throw new SQLNonTransientException(msg);
                }
                if (nodeValuesMap.get(nodeIndex) == null) {
                    nodeValuesMap.put(nodeIndex, new ArrayList<ValuesClause>());
                }
                nodeValuesMap.get(nodeIndex).add(valueClause);
            }
            RouteResultsetNode[] nodes = new RouteResultsetNode[nodeValuesMap.size()];
            int count = 0;
            for (Map.Entry<Integer, List<ValuesClause>> node : nodeValuesMap.entrySet()) {
                Integer nodeIndex = node.getKey();
                List<ValuesClause> valuesList = node.getValue();
                insertStmt.setValuesList(valuesList);
                nodes[count] = new RouteResultsetNode(tableConfig.getDataNodes().get(nodeIndex), rrs.getSqlType(), insertStmt.toString());
                if (algorithm instanceof SlotFunction) {
                    nodes[count].setSlot(slotsMap.get(nodeIndex));
                    nodes[count].setStatement(ParseUtil.changeInsertAddSlot(nodes[count].getStatement(), nodes[count].getSlot()));
                }
                nodes[count++].setSource(rrs);
            }
            rrs.setNodes(nodes);
            rrs.setFinishedRoute(true);
        }
    } else if (insertStmt.getQuery() != null) {
        // insert into .... select ....
        String msg = "TODO:insert into .... select .... not supported!";
        LOGGER.warn(msg);
        throw new SQLNonTransientException(msg);
    }
}
Also used : AbstractPartitionAlgorithm(io.mycat.route.function.AbstractPartitionAlgorithm) SQLCharExpr(com.alibaba.druid.sql.ast.expr.SQLCharExpr) HashMap(java.util.HashMap) SQLExpr(com.alibaba.druid.sql.ast.SQLExpr) SlotFunction(io.mycat.route.function.SlotFunction) SQLNonTransientException(java.sql.SQLNonTransientException) RouteResultsetNode(io.mycat.route.RouteResultsetNode) TableConfig(io.mycat.config.model.TableConfig) SQLIntegerExpr(com.alibaba.druid.sql.ast.expr.SQLIntegerExpr) ArrayList(java.util.ArrayList) List(java.util.List) HashMap(java.util.HashMap) Map(java.util.Map) ValuesClause(com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause)

Example 52 with TableConfig

use of io.mycat.config.model.TableConfig in project Mycat_plus by coderczp.

the class DruidLockTableParser method statementParse.

@Override
public void statementParse(SchemaConfig schema, RouteResultset rrs, SQLStatement stmt) throws SQLNonTransientException {
    MySqlLockTableStatement lockTableStat = (MySqlLockTableStatement) stmt;
    String table = lockTableStat.getTableSource().toString().toUpperCase();
    TableConfig tableConfig = schema.getTables().get(table);
    if (tableConfig == null) {
        String msg = "can't find table define of " + table + " in schema:" + schema.getName();
        LOGGER.warn(msg);
        throw new SQLNonTransientException(msg);
    }
    LockType lockType = lockTableStat.getLockType();
    if (LockType.WRITE != lockType && LockType.READ != lockType) {
        String msg = "lock type must be write or read";
        LOGGER.warn(msg);
        throw new SQLNonTransientException(msg);
    }
    List<String> dataNodes = tableConfig.getDataNodes();
    RouteResultsetNode[] nodes = new RouteResultsetNode[dataNodes.size()];
    for (int i = 0; i < dataNodes.size(); i++) {
        nodes[i] = new RouteResultsetNode(dataNodes.get(i), ServerParse.LOCK, stmt.toString());
    }
    rrs.setNodes(nodes);
    rrs.setFinishedRoute(true);
}
Also used : SQLNonTransientException(java.sql.SQLNonTransientException) MySqlLockTableStatement(com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlLockTableStatement) RouteResultsetNode(io.mycat.route.RouteResultsetNode) TableConfig(io.mycat.config.model.TableConfig) LockType(com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlLockTableStatement.LockType)

Example 53 with TableConfig

use of io.mycat.config.model.TableConfig in project Mycat_plus by coderczp.

the class DruidMycatRouteStrategy method routeNormalSqlWithAST.

@Override
public RouteResultset routeNormalSqlWithAST(SchemaConfig schema, String stmt, RouteResultset rrs, String charset, LayerCachePool cachePool, int sqlType, ServerConnection sc) 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());
    if (visitor.isSubqueryRelationOr()) {
        String err = "In subQuery,the or condition is not supported.";
        LOGGER.error(err);
        throw new SQLSyntaxErrorException(err);
    }
    /* 按照以下情况路由
			1.2.1 可以直接路由.
       		1.2.2 两个表夸库join的sql.调用calat
       		1.2.3 需要先执行subquery 的sql.把subquery拆分出来.获取结果后,与outerquery
		 */
    // add huangyiming 分片规则不一样的且表中带查询条件的则走Catlet
    List<String> tables = ctx.getTables();
    SchemaConfig schemaConf = MycatServer.getInstance().getConfig().getSchemas().get(schema.getName());
    int index = 0;
    RuleConfig firstRule = null;
    boolean directRoute = true;
    Set<String> firstDataNodes = new HashSet<String>();
    Map<String, TableConfig> tconfigs = schemaConf == null ? null : schemaConf.getTables();
    Map<String, RuleConfig> rulemap = new HashMap<>();
    if (tconfigs != null) {
        for (String tableName : tables) {
            TableConfig tc = tconfigs.get(tableName);
            if (tc == null) {
                // add 别名中取
                Map<String, String> tableAliasMap = ctx.getTableAliasMap();
                if (tableAliasMap != null && tableAliasMap.get(tableName) != null) {
                    tc = schemaConf.getTables().get(tableAliasMap.get(tableName));
                }
            }
            if (index == 0) {
                if (tc != null) {
                    firstRule = tc.getRule();
                    // 没有指定分片规则时,不做处理
                    if (firstRule == null) {
                        continue;
                    }
                    firstDataNodes.addAll(tc.getDataNodes());
                    rulemap.put(tc.getName(), firstRule);
                }
            } else {
                if (tc != null) {
                    // ER关系表的时候是可能存在字表中没有tablerule的情况,所以加上判断
                    RuleConfig ruleCfg = tc.getRule();
                    if (ruleCfg == null) {
                        // 没有指定分片规则时,不做处理
                        continue;
                    }
                    Set<String> dataNodes = new HashSet<String>();
                    dataNodes.addAll(tc.getDataNodes());
                    rulemap.put(tc.getName(), ruleCfg);
                    // 如果匹配规则不相同或者分片的datanode不相同则需要走子查询处理
                    if (firstRule != null && ((ruleCfg != null && !ruleCfg.getRuleAlgorithm().equals(firstRule.getRuleAlgorithm())) || (!dataNodes.equals(firstDataNodes)))) {
                        directRoute = false;
                        break;
                    }
                }
            }
            index++;
        }
    }
    RouteResultset rrsResult = rrs;
    if (directRoute) {
        // 直接路由
        if (!RouterUtil.isAllGlobalTable(ctx, schemaConf)) {
            if (rulemap.size() > 1 && !checkRuleField(rulemap, visitor)) {
                String err = "In case of slice table,there is no rule field in the relationship condition!";
                LOGGER.error(err);
                throw new SQLSyntaxErrorException(err);
            }
        }
        rrsResult = directRoute(rrs, ctx, schema, druidParser, statement, cachePool);
    } else {
        int subQuerySize = visitor.getSubQuerys().size();
        if (subQuerySize == 0 && ctx.getTables().size() == 2) {
            // 两表关联,考虑使用catlet
            if (!visitor.getRelationships().isEmpty()) {
                rrs.setCacheAble(false);
                rrs.setFinishedRoute(true);
                rrsResult = catletRoute(schema, ctx.getSql(), charset, sc);
            } else {
                rrsResult = directRoute(rrs, ctx, schema, druidParser, statement, cachePool);
            }
        } else if (subQuerySize == 1) {
            // 只涉及一张表的子查询,使用  MiddlerResultHandler 获取中间结果后,改写原有 sql 继续执行 TODO 后期可能会考虑多个子查询的情况.
            SQLSelect sqlselect = visitor.getSubQuerys().iterator().next();
            if (!visitor.getRelationships().isEmpty()) {
                // 当 inner query  和 outer  query  有关联条件时,暂不支持
                String err = "In case of slice table,sql have different rules,the relationship condition is not supported.";
                LOGGER.error(err);
                throw new SQLSyntaxErrorException(err);
            } else {
                SQLSelectQuery sqlSelectQuery = sqlselect.getQuery();
                if (((MySqlSelectQueryBlock) sqlSelectQuery).getFrom() instanceof SQLExprTableSource) {
                    rrs.setCacheAble(false);
                    rrs.setFinishedRoute(true);
                    rrsResult = middlerResultRoute(schema, charset, sqlselect, sqlType, statement, sc);
                }
            }
        } else if (subQuerySize >= 2) {
            String err = "In case of slice table,sql has different rules,currently only one subQuery is supported.";
            LOGGER.error(err);
            throw new SQLSyntaxErrorException(err);
        }
    }
    return rrsResult;
}
Also used : SchemaConfig(io.mycat.config.model.SchemaConfig) MycatStatementParser(io.mycat.route.parser.druid.MycatStatementParser) MycatSchemaStatVisitor(io.mycat.route.parser.druid.MycatSchemaStatVisitor) HashMap(java.util.HashMap) SQLSyntaxErrorException(java.sql.SQLSyntaxErrorException) SQLSelectQuery(com.alibaba.druid.sql.ast.statement.SQLSelectQuery) SQLStatement(com.alibaba.druid.sql.ast.SQLStatement) TableConfig(io.mycat.config.model.TableConfig) MySqlStatementParser(com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser) HashSet(java.util.HashSet) RouteResultset(io.mycat.route.RouteResultset) DruidShardingParseInfo(io.mycat.route.parser.druid.DruidShardingParseInfo) SQLStatementParser(com.alibaba.druid.sql.parser.SQLStatementParser) SQLSelect(com.alibaba.druid.sql.ast.statement.SQLSelect) MySqlSelectQueryBlock(com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock) SQLNonTransientException(java.sql.SQLNonTransientException) SQLSyntaxErrorException(java.sql.SQLSyntaxErrorException) DruidParser(io.mycat.route.parser.druid.DruidParser) SQLExprTableSource(com.alibaba.druid.sql.ast.statement.SQLExprTableSource) RuleConfig(io.mycat.config.model.rule.RuleConfig)

Example 54 with TableConfig

use of io.mycat.config.model.TableConfig in project Mycat_plus by coderczp.

the class DruidParserFactory method getDruidParserForMultiDB.

private static DruidParser getDruidParserForMultiDB(SchemaConfig schema, SQLStatement statement, SchemaStatVisitor visitor) {
    DruidParser parser = null;
    // 先解出表,判断表所在db的类型,再根据不同db类型返回不同的解析
    /**
     * 不能直接使用visitor变量,防止污染后续sql解析
     * @author SvenAugustus
     */
    SchemaStatVisitor _visitor = SchemaStatVisitorFactory.create(schema);
    List<String> tables = parseTables(statement, _visitor);
    for (String table : tables) {
        Set<String> dbTypes = null;
        TableConfig tableConfig = schema.getTables().get(table);
        if (tableConfig == null) {
            dbTypes = new HashSet<>();
            dbTypes.add(schema.getDefaultDataNodeDbType());
        } else {
            dbTypes = tableConfig.getDbTypes();
        }
        if (dbTypes.contains("oracle")) {
            parser = new DruidSelectOracleParser();
            break;
        } else if (dbTypes.contains("db2")) {
            parser = new DruidSelectDb2Parser();
            break;
        } else if (dbTypes.contains("sqlserver")) {
            parser = new DruidSelectSqlServerParser();
            break;
        } else if (dbTypes.contains("postgresql")) {
            parser = new DruidSelectPostgresqlParser();
            break;
        }
    }
    return parser;
}
Also used : DruidSelectOracleParser(io.mycat.route.parser.druid.impl.DruidSelectOracleParser) DruidSelectSqlServerParser(io.mycat.route.parser.druid.impl.DruidSelectSqlServerParser) DefaultDruidParser(io.mycat.route.parser.druid.impl.DefaultDruidParser) DruidSelectDb2Parser(io.mycat.route.parser.druid.impl.DruidSelectDb2Parser) DruidSelectPostgresqlParser(io.mycat.route.parser.druid.impl.DruidSelectPostgresqlParser) TableConfig(io.mycat.config.model.TableConfig) SchemaStatVisitor(com.alibaba.druid.sql.visitor.SchemaStatVisitor)

Example 55 with TableConfig

use of io.mycat.config.model.TableConfig in project Mycat_plus by coderczp.

the class ConfigComparer method loadMigratorTables.

/*
	 * 加载迁移表信息,tables大小为0表示迁移schema下所有表
	 */
private void loadMigratorTables(String schemaName, String[] tables) {
    if (!DataMigratorUtil.isKeyExistIgnoreCase(oldSchemas, schemaName)) {
        throw new ConfigException("oldSchema:" + schemaName + " is not exists!");
    }
    if (!DataMigratorUtil.isKeyExistIgnoreCase(newSchemas, schemaName)) {
        throw new ConfigException("newSchema:" + schemaName + " is not exists!");
    }
    Map<String, TableConfig> oldTables = DataMigratorUtil.getValueIgnoreCase(oldSchemas, schemaName).getTables();
    Map<String, TableConfig> newTables = DataMigratorUtil.getValueIgnoreCase(newSchemas, schemaName).getTables();
    if (tables.length > 0) {
        // 指定schema下的表进行迁移
        for (int i = 0; i < tables.length; i++) {
            TableConfig oldTable = DataMigratorUtil.getValueIgnoreCase(oldTables, tables[i]);
            TableConfig newTable = DataMigratorUtil.getValueIgnoreCase(newTables, tables[i]);
            loadMigratorTable(oldTable, newTable, schemaName, tables[i]);
        }
    } else {
        // 迁移schema下所有的表
        // 校验新旧schema中的table配置是否一致
        Set<String> oldSet = oldTables.keySet();
        Set<String> newSet = newTables.keySet();
        if (!oldSet.equals(newSet)) {
            throw new ConfigException("new & old table config is not equal!");
        }
        for (String tableName : oldSet) {
            TableConfig oldTable = oldTables.get(tableName);
            TableConfig newTable = newTables.get(tableName);
            loadMigratorTable(oldTable, newTable, schemaName, tableName);
        }
    }
}
Also used : TableConfig(io.mycat.config.model.TableConfig) ConfigException(io.mycat.config.util.ConfigException)

Aggregations

TableConfig (io.mycat.config.model.TableConfig)84 SchemaConfig (io.mycat.config.model.SchemaConfig)26 SQLNonTransientException (java.sql.SQLNonTransientException)26 Test (org.junit.Test)18 RuleConfig (io.mycat.config.model.rule.RuleConfig)16 RouteResultset (io.mycat.route.RouteResultset)14 AbstractPartitionAlgorithm (io.mycat.route.function.AbstractPartitionAlgorithm)14 HashMap (java.util.HashMap)14 MySqlStatementParser (com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser)12 SlotFunction (io.mycat.route.function.SlotFunction)12 ArrayList (java.util.ArrayList)12 SQLStatement (com.alibaba.druid.sql.ast.SQLStatement)10 MySqlInsertStatement (com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement)8 PhysicalDBNode (io.mycat.backend.datasource.PhysicalDBNode)8 ConfigException (io.mycat.config.util.ConfigException)8 RouteResultsetNode (io.mycat.route.RouteResultsetNode)8 HashSet (java.util.HashSet)8 SQLCharExpr (com.alibaba.druid.sql.ast.expr.SQLCharExpr)6 SQLIdentifierExpr (com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr)6 CacheService (io.mycat.cache.CacheService)6