private RouteResultset routeWithPartitionColumn( SchemaConfig schema, TableConfig tc, QueryTreeNode ast, InsertParseInf parsInf, RouteResultset rrs, String stmt, LayerCachePool cachePool) throws SQLNonTransientException { String partColumn = tc.getPartitionColumn(); if (partColumn != null) { String sharindVal = parsInf.columnPairMap.get(partColumn); if (sharindVal != null) { Set<ColumnRoutePair> col2Val = new HashSet<ColumnRoutePair>(1); col2Val.add(new ColumnRoutePair(sharindVal)); return tryRouteForTable(ast, schema, rrs, false, stmt, tc, col2Val, null, cachePool); } else { // must provide sharding_id when insert String inf = "bad insert sql (sharding column:" + partColumn + " not provided," + stmt; LOGGER.warn(inf); throw new SQLNonTransientException(inf); } } return null; }
/** * 简单描述该方法的实现功能 * * @param ast QueryTreeNode * @param schema 数据库名 * @param rrs 数据路由集合 * @param isSelect 是否是select语句标志 * @param sql 执行语句 * @param tc 表实体 * @param ruleCol2Val 一个ColumnRoutePair集合 * @param allColConds 一个ColumnRoutePair集合 * @param cachePool * @return 一个数据路由集合 * @throws SQLNonTransientException * @author mycat */ private RouteResultset tryRouteForTable( QueryTreeNode ast, SchemaConfig schema, RouteResultset rrs, boolean isSelect, String sql, TableConfig tc, Set<ColumnRoutePair> ruleCol2Val, Map<String, Set<ColumnRoutePair>> allColConds, LayerCachePool cachePool) throws SQLNonTransientException { if (tc.getTableType() == TableConfig.TYPE_GLOBAL_TABLE && isSelect) { sql = addSQLLmit(schema, rrs, ast, sql); return RouterUtil.routeToSingleNode(rrs, tc.getRandomDataNode(), sql); } // no partion define or no where condtion for this table or no // partion column condtions boolean cache = isSelect; if (ruleCol2Val == null || ruleCol2Val.isEmpty()) { if (tc.isRuleRequired()) { throw new IllegalArgumentException( "route rule for table " + tc.getName() + " is required: " + sql); } else if (allColConds != null && allColConds.size() == 1) { // try if can route by ER relation if (tc.isSecondLevel() && tc.getParentTC().getPartitionColumn().equals(tc.getParentKey())) { Set<ColumnRoutePair> joinKeyPairs = allColConds.get(tc.getJoinKey()); if (joinKeyPairs != null) { Set<String> dataNodeSet = RouterUtil.ruleCalculate(tc.getParentTC(), joinKeyPairs); if (dataNodeSet.isEmpty()) { throw new SQLNonTransientException("parent key can't find any valid datanode "); } if (LOGGER.isDebugEnabled()) { LOGGER.debug( "found partion nodes (using parent partion rule directly) for child table to update " + Arrays.toString(dataNodeSet.toArray()) + " sql :" + sql); } if (dataNodeSet.size() > 1) { return routeToMultiNode(schema, isSelect, isSelect, ast, rrs, dataNodeSet, sql); } else { rrs.setCacheAble(true); return RouterUtil.routeToSingleNode(rrs, dataNodeSet.iterator().next(), sql); } } } // try by primary key if found in cache Set<ColumnRoutePair> primaryKeyPairs = allColConds.get(tc.getPrimaryKey()); if (primaryKeyPairs != null) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("try to find cache by primary key "); } cache = false; Set<String> dataNodes = new HashSet<String>(primaryKeyPairs.size()); boolean allFound = true; String tableKey = schema.getName() + '_' + tc.getName(); for (ColumnRoutePair pair : primaryKeyPairs) { String cacheKey = pair.colValue; String dataNode = (String) cachePool.get(tableKey, cacheKey); if (dataNode == null) { allFound = false; break; } else { dataNodes.add(dataNode); } } if (allFound) { return routeToMultiNode(schema, isSelect, isSelect, ast, rrs, dataNodes, sql); } // need cache primary key ->datanode relation if (isSelect && tc.getPrimaryKey() != null) { rrs.setPrimaryKey(tableKey + '.' + tc.getPrimaryKey()); } } } return routeToMultiNode(schema, isSelect, cache, ast, rrs, tc.getDataNodes(), sql); } // match table with where condtion of partion colum values Set<String> dataNodeSet = RouterUtil.ruleCalculate(tc, ruleCol2Val); if (dataNodeSet.size() == 1) { rrs.setCacheAble(isSelect); return RouterUtil.routeToSingleNode(rrs, dataNodeSet.iterator().next(), sql); } else { return routeToMultiNode(schema, isSelect, isSelect, ast, rrs, dataNodeSet, sql); } }