Ejemplo n.º 1
0
  /**
   * 单表路由
   *
   * @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());
        }
      }
    }
  }
Ejemplo n.º 2
0
  /**
   * 多表路由
   *
   * @param schema
   * @param ctx
   * @param tables
   * @param rrs
   * @param isSelect
   * @return
   * @throws SQLNonTransientException
   */
  public static RouteResultset tryRouteForTables(
      SchemaConfig schema,
      DruidShardingParseInfo ctx,
      RouteCalculateUnit routeUnit,
      RouteResultset rrs,
      boolean isSelect,
      LayerCachePool cachePool)
      throws SQLNonTransientException {
    List<String> tables = ctx.getTables();
    if (schema.isNoSharding() || (tables.size() >= 1 && isNoSharding(schema, tables.get(0)))) {
      return routeToSingleNode(rrs, schema.getDataNode(), ctx.getSql());
    }

    // 只有一个表的
    if (tables.size() == 1) {
      return RouterUtil.tryRouteForOneTable(
          schema, ctx, routeUnit, tables.get(0), rrs, isSelect, cachePool);
    }

    Set<String> retNodesSet = new HashSet<String>();
    // 每个表对应的路由映射
    Map<String, Set<String>> tablesRouteMap = new HashMap<String, Set<String>>();

    // 分库解析信息不为空
    Map<String, Map<String, Set<ColumnRoutePair>>> tablesAndConditions =
        routeUnit.getTablesAndConditions();
    if (tablesAndConditions != null && tablesAndConditions.size() > 0) {
      // 为分库表找路由
      RouterUtil.findRouteWithcConditionsForTables(
          schema, rrs, tablesAndConditions, tablesRouteMap, ctx.getSql(), cachePool, isSelect);
      if (rrs.isFinishedRoute()) {
        return rrs;
      }
    }

    // 为全局表和单库表找路由
    for (String tableName : tables) {
      TableConfig tableConfig = schema.getTables().get(tableName.toUpperCase());
      if (tableConfig == null) {
        String msg =
            "can't find table define in schema " + tableName + " schema:" + schema.getName();
        LOGGER.warn(msg);
        throw new SQLNonTransientException(msg);
      }
      if (tableConfig.isGlobalTable()) { // 全局表
        if (tablesRouteMap.get(tableName) == null) {
          tablesRouteMap.put(tableName, new HashSet<String>());
        }
        tablesRouteMap.get(tableName).addAll(tableConfig.getDataNodes());
      } else if (tablesRouteMap.get(tableName) == null) { // 余下的表都是单库表
        tablesRouteMap.put(tableName, new HashSet<String>());
        tablesRouteMap.get(tableName).addAll(tableConfig.getDataNodes());
      }
    }

    boolean isFirstAdd = true;
    for (Map.Entry<String, Set<String>> entry : tablesRouteMap.entrySet()) {
      if (entry.getValue() == null || entry.getValue().size() == 0) {
        throw new SQLNonTransientException("parent key can't find any valid datanode ");
      } else {
        if (isFirstAdd) {
          retNodesSet.addAll(entry.getValue());
          isFirstAdd = false;
        } else {
          retNodesSet.retainAll(entry.getValue());
          if (retNodesSet.size() == 0) { // 两个表的路由无交集
            String errMsg =
                "invalid route in sql, multi tables found but datanode has no intersection "
                    + " sql:"
                    + ctx.getSql();
            LOGGER.warn(errMsg);
            throw new SQLNonTransientException(errMsg);
          }
        }
      }
    }

    if (retNodesSet != null && retNodesSet.size() > 0) {
      if (retNodesSet.size() > 1 && isAllGlobalTable(ctx, schema)) {
        // mulit routes ,not cache route result
        if (isSelect) {
          rrs.setCacheAble(false);
          routeToSingleNode(rrs, retNodesSet.iterator().next(), ctx.getSql());
        } else { // delete 删除全局表的记录
          routeToMultiNode(isSelect, rrs, retNodesSet, ctx.getSql(), true);
        }

      } else {
        routeToMultiNode(isSelect, rrs, retNodesSet, ctx.getSql());
      }
    }
    return rrs;
  }