/** * 根据 ER分片规则获取路由集合 * * @param stmt 执行的语句 * @param rrs 数据路由集合 * @param tc 表实体 * @param joinKeyVal 连接属性 * @return RouteResultset(数据路由集合) * @throws SQLNonTransientException * @author mycat */ public static RouteResultset routeByERParentKey( String stmt, RouteResultset rrs, TableConfig tc, String joinKeyVal) throws SQLNonTransientException { // only has one parent level and ER parent key is parent // table's partition key if (tc.isSecondLevel() && tc.getParentTC().getPartitionColumn().equals(tc.getParentKey())) { // using // parent // rule to // find // datanode Set<ColumnRoutePair> parentColVal = new HashSet<ColumnRoutePair>(1); ColumnRoutePair pair = new ColumnRoutePair(joinKeyVal); parentColVal.add(pair); Set<String> dataNodeSet = ruleCalculate(tc.getParentTC(), parentColVal); if (dataNodeSet.isEmpty() || dataNodeSet.size() > 1) { throw new SQLNonTransientException( "parent key can't find valid datanode ,expect 1 but found: " + dataNodeSet.size()); } String dn = dataNodeSet.iterator().next(); if (LOGGER.isDebugEnabled()) { LOGGER.debug( "found partion node (using parent partion rule directly) for child table to insert " + dn + " sql :" + stmt); } return RouterUtil.routeToSingleNode(rrs, dn, stmt); } return null; }
/** * 单表路由 * * @param schema * @param ctx * @param tableName * @param rrs * @param isSelect * @return * @throws SQLNonTransientException */ public static RouteResultset tryRouteForOneTable( SchemaConfig schema, DruidShardingParseInfo ctx, RouteCalculateUnit routeUnit, String tableName, RouteResultset rrs, boolean isSelect, LayerCachePool cachePool) throws SQLNonTransientException { if (isNoSharding(schema, tableName)) { return routeToSingleNode(rrs, schema.getDataNode(), ctx.getSql()); } TableConfig tc = schema.getTables().get(tableName); if (tc == null) { String msg = "can't find table define in schema " + tableName + " schema:" + schema.getName(); LOGGER.warn(msg); throw new SQLNonTransientException(msg); } if (tc.isGlobalTable()) { // 全局表 if (isSelect) { // global select ,not cache route result rrs.setCacheAble(false); return routeToSingleNode(rrs, tc.getRandomDataNode(), ctx.getSql()); } else { // insert into 全局表的记录 return routeToMultiNode(false, rrs, tc.getDataNodes(), ctx.getSql(), true); } } else { // 单表或者分库表 if (!checkRuleRequired(schema, ctx, routeUnit, tc)) { throw new IllegalArgumentException( "route rule for table " + tc.getName() + " is required: " + ctx.getSql()); } if (tc.getPartitionColumn() == null && !tc.isSecondLevel()) { // 单表且不是childTable // return RouterUtil.routeToSingleNode(rrs, tc.getDataNodes().get(0),ctx.getSql()); return routeToMultiNode(rrs.isCacheAble(), rrs, tc.getDataNodes(), ctx.getSql()); } else { // 每个表对应的路由映射 Map<String, Set<String>> tablesRouteMap = new HashMap<String, Set<String>>(); if (routeUnit.getTablesAndConditions() != null && routeUnit.getTablesAndConditions().size() > 0) { RouterUtil.findRouteWithcConditionsForTables( schema, rrs, routeUnit.getTablesAndConditions(), tablesRouteMap, ctx.getSql(), cachePool, isSelect); if (rrs.isFinishedRoute()) { return rrs; } } if (tablesRouteMap.get(tableName) == null) { return routeToMultiNode(rrs.isCacheAble(), rrs, tc.getDataNodes(), ctx.getSql()); } else { // boolean isCache = rrs.isCacheAble(); // if(tablesRouteMap.get(tableName).size() > 1) { // // } return routeToMultiNode( rrs.isCacheAble(), rrs, tablesRouteMap.get(tableName), ctx.getSql()); } } } }
/** @return dataNodeIndex -> [partitionKeysValueTuple+] */ public static Set<String> ruleByJoinValueCalculate( RouteResultset rrs, TableConfig tc, Set<ColumnRoutePair> colRoutePairSet) throws SQLNonTransientException { String joinValue = ""; if (colRoutePairSet.size() > 1) { LOGGER.warn("joinKey can't have multi Value"); } else { Iterator it = colRoutePairSet.iterator(); ColumnRoutePair joinCol = (ColumnRoutePair) it.next(); joinValue = joinCol.colValue; } Set<String> retNodeSet = new LinkedHashSet<String>(); Set<String> nodeSet = new LinkedHashSet<String>(); if (tc.isSecondLevel() && tc.getParentTC().getPartitionColumn().equals(tc.getParentKey())) { // using // parent // rule to // find // datanode nodeSet = ruleCalculate(tc.getParentTC(), colRoutePairSet); if (nodeSet.isEmpty()) { throw new SQLNonTransientException( "parent key can't find valid datanode ,expect 1 but found: " + nodeSet.size()); } if (LOGGER.isDebugEnabled()) { LOGGER.debug( "found partion node (using parent partion rule directly) for child table to insert " + nodeSet + " sql :" + rrs.getStatement()); } retNodeSet.addAll(nodeSet); // for(ColumnRoutePair pair : colRoutePairSet) { // nodeSet = ruleCalculate(tc.getParentTC(),colRoutePairSet); // if (nodeSet.isEmpty() || nodeSet.size() > 1) {//an exception would be thrown, if sql was // executed on more than on sharding // throw new SQLNonTransientException( // "parent key can't find valid datanode ,expect 1 but found: " // + nodeSet.size()); // } // String dn = nodeSet.iterator().next(); // if (LOGGER.isDebugEnabled()) { // LOGGER.debug("found partion node (using parent partion rule directly) for child table // to insert " // + dn + " sql :" + rrs.getStatement()); // } // retNodeSet.addAll(nodeSet); // } return retNodeSet; } else { retNodeSet.addAll(tc.getParentTC().getDataNodes()); } return retNodeSet; }