private boolean isDirectLookup() {
   for (TableFilter tf : filters) {
     if (!tf.isFromTableMate() && !isNestedJoinTable(tf)) {
       return false;
     }
   }
   if (filters.size() == 1) {
     return true;
   } else {
     List<TableFilter> shardingTableFilter = New.arrayList();
     for (TableFilter tf : filters) {
       if (isNestedJoinTable(tf)) {
         continue;
       }
       if (!isGropTableFilter(tf)) {
         return false;
       }
       TableMate table = (TableMate) tf.getTable();
       if (table.getRuleColumns() != null) {
         shardingTableFilter.add(tf);
       }
     }
     if (shardingTableFilter.size() < 2) {
       return true;
     }
     this.joinTableChain = New.hashSet();
     evaluationJoinChain(shardingTableFilter.iterator().next());
     return joinTableChain.containsAll(shardingTableFilter);
   }
 }
    private void evaluationJoinChain(TableFilter filter) {
      TableMate table1 = (TableMate) filter.getTable();
      Column[] columns1 = table1.getRuleColumns();
      if (columns1 == null) {
        throw new IllegalArgumentException("not sharding TableFilter");
      }
      ArrayList<IndexCondition> conditions = getIndexConditions(filter);
      List<IndexCondition> masks = New.arrayList(10);
      List<Column> compareColumns = New.arrayList(10);
      for (Column column : columns1) {
        for (IndexCondition condition : conditions) {
          Column compareColumn = condition.getCompareColumn();
          if ((condition.getMask(conditions) & IndexCondition.EQUALITY)
              != IndexCondition.EQUALITY) {
            continue;
          }
          if (condition.getColumn() != column || compareColumn == null) {
            continue;
          }
          masks.add(condition);
          compareColumns.add(compareColumn);
        }
      }

      Set<Table> tables = New.hashSet();
      for (IndexCondition mask : masks) {
        Column compareColumn = mask.getCompareColumn();
        Table table = compareColumn.getTable();
        if (!(table instanceof TableMate)) {
          continue;
        }
        TableMate tableMate = (TableMate) table;
        Column[] rc = tableMate.getRuleColumns();
        if (compareColumns.containsAll(Arrays.asList(rc))) {
          tables.add(table);
        }
      }
      if (tables.isEmpty()) {
        return;
      }
      for (Table table : tables) {
        for (TableFilter tf : filters) {
          if (tf.getTable() == table && !joinTableChain.contains(tf)) {
            joinTableChain.add(tf);
            evaluationJoinChain(tf);
          }
        }
      }
    }
 private boolean isGropTableFilter(TableFilter filter) {
   TableMate table1 = (TableMate) filter.getTable();
   for (TableFilter item : filters) {
     if (item == filter || isNestedJoinTable(item)) {
       continue;
     }
     TableMate table2 = (TableMate) item.getTable();
     TableRule rule1 = table1.getTableRule();
     TableRule rule2 = table2.getTableRule();
     if (!rule1.isNodeComparable(rule2)) {
       return false;
     }
   }
   return true;
 }
 private DirectLookupEstimator(ArrayList<TableFilter> topFilters) {
   this.filters = New.arrayList();
   this.joinCond = New.arrayList();
   for (TableFilter f : topFilters) {
     f.visit(
         new TableFilterVisitor() {
           @Override
           public void accept(TableFilter f) {
             filters.add(f);
             if (f.getJoinCondition() != null) {
               joinCond.add(f.getJoinCondition());
             }
           }
         });
   }
 }
 private ArrayList<IndexCondition> getIndexConditions(TableFilter filter) {
   ArrayList<IndexCondition> indexConditions = filter.getIndexConditions();
   if (joinCond.isEmpty()) {
     return indexConditions;
   }
   ArrayList<IndexCondition> original = New.arrayList(indexConditions);
   ArrayList<IndexCondition> result;
   try {
     for (Expression cond : joinCond) {
       // add to indexConditions
       cond.createIndexConditions(filter.getSession(), filter);
     }
     result = New.arrayList(indexConditions);
     return result;
   } finally {
     indexConditions.clear();
     indexConditions.addAll(original);
   }
 }
 private RoutingResult doRoute(Select prepare) {
   List<TableFilter> filters = filterNotTableMate(prepare.getTopTableFilter());
   List<TableFilter> shards = New.arrayList(filters.size());
   List<TableFilter> globals = New.arrayList(filters.size());
   List<TableFilter> fixeds = New.arrayList(filters.size());
   for (TableFilter tf : filters) {
     TableMate table = getTableMate(tf);
     switch (table.getTableRule().getType()) {
       case TableRule.SHARDED_NODE_TABLE:
         shards.add(tf);
         break;
       case TableRule.GLOBAL_NODE_TABLE:
         globals.add(tf);
         break;
       case TableRule.FIXED_NODE_TABLE:
         fixeds.add(tf);
         break;
       default:
         break;
     }
   }
   RoutingResult result = null;
   if (!shards.isEmpty()) {
     for (TableFilter f : shards) {
       f.setEvaluatable(f, false);
       if (f.isJoinOuter() || f.isJoinOuterIndirect()) {
         prepare.getCondition().createIndexConditions(session, f);
       }
       TableMate table = getTableMate(f);
       ConditionExtractor extractor = new ConditionExtractor(f);
       RoutingResult r =
           routingHandler.doRoute(
               table, extractor.getStart(), extractor.getEnd(), extractor.getInColumns());
       result = (result == null || r.compareTo(result) < 0) ? r : result;
     }
     for (TableFilter f : shards) {
       f.setEvaluatable(f, true);
     }
   } else if (!fixeds.isEmpty()) {
     for (TableFilter tf : shards) {
       TableMate table = getTableMate(tf);
       RoutingResult r = routingHandler.doRoute(table);
       result = r;
     }
   } else if (!globals.isEmpty()) {
     // 全部为全局表查询,随机取一个第一个表结点
     GlobalTableRule tableRule = (GlobalTableRule) getTableRule(globals.iterator().next());
     RoutingResult r = tableRule.getRandomRoutingResult();
     result = r;
   } else {
     throw DbException.throwInternalError("SQL_ROUTING_ERROR");
   }
   ObjectNode[] selectNodes = result.getSelectNodes();
   if (selectNodes.length == 0) {
     throw DbException.throwInternalError("SQL_ROUTING_ERROR,empty result");
   }
   setConsistencyTableNodes(selectNodes, filters);
   return result;
 }
 private boolean isNestedJoinTable(TableFilter f) {
   return f.getTable() instanceof RangeTable
       && StringUtils.startsWith(f.getTableAlias(), Constants.PREFIX_JOIN);
 }