private static TupleFilter buildInFilter(
      TblColRef[] hostCols, Set<Array<String>> satisfyingHostRecords) {
    if (satisfyingHostRecords.size() == 0) {
      return ConstantTupleFilter.FALSE;
    }

    int hn = hostCols.length;
    if (hn == 1) {
      CompareTupleFilter in = new CompareTupleFilter(FilterOperatorEnum.IN);
      in.addChild(new ColumnTupleFilter(hostCols[0]));
      in.addChild(new ConstantTupleFilter(asValues(satisfyingHostRecords)));
      return in;
    } else {
      LogicalTupleFilter or = new LogicalTupleFilter(FilterOperatorEnum.OR);
      for (Array<String> rec : satisfyingHostRecords) {
        LogicalTupleFilter and = new LogicalTupleFilter(FilterOperatorEnum.AND);
        for (int i = 0; i < hn; i++) {
          CompareTupleFilter eq = new CompareTupleFilter(FilterOperatorEnum.EQ);
          eq.addChild(new ColumnTupleFilter(hostCols[i]));
          eq.addChild(new ConstantTupleFilter(rec.data[i]));
          and.addChild(eq);
        }
        or.addChild(and);
      }
      return or;
    }
  }
 private static LogicalTupleFilter buildRangeFilter(
     TblColRef[] hostCols, Set<Array<String>> satisfyingHostRecords) {
   int hn = hostCols.length;
   String[] min = new String[hn];
   String[] max = new String[hn];
   findMinMax(satisfyingHostRecords, hostCols, min, max);
   LogicalTupleFilter and = new LogicalTupleFilter(FilterOperatorEnum.AND);
   for (int i = 0; i < hn; i++) {
     CompareTupleFilter compMin = new CompareTupleFilter(FilterOperatorEnum.GTE);
     compMin.addChild(new ColumnTupleFilter(hostCols[i]));
     compMin.addChild(new ConstantTupleFilter(min[i]));
     and.addChild(compMin);
     CompareTupleFilter compMax = new CompareTupleFilter(FilterOperatorEnum.LTE);
     compMax.addChild(new ColumnTupleFilter(hostCols[i]));
     compMax.addChild(new ConstantTupleFilter(max[i]));
     and.addChild(compMax);
   }
   return and;
 }