public BottomUpJoinIterator(EvaluationStrategy strategy, Join join, BindingSet bindings)
      throws QueryEvaluationException {
    leftIter = strategy.evaluate(join.getLeftArg(), bindings);
    rightIter = strategy.evaluate(join.getRightArg(), bindings);

    joinAttributes = join.getLeftArg().getBindingNames();
    joinAttributes.retainAll(join.getRightArg().getBindingNames());

    hashTable = null;
  }
 @Override
 public void meet(Join join) {
   if (join.getLeftArg().getBindingNames().containsAll(filterVars)) {
     // All required vars are bound by the left expr
     join.getLeftArg().visit(this);
   } else if (join.getRightArg().getBindingNames().containsAll(filterVars)) {
     // All required vars are bound by the right expr
     join.getRightArg().visit(this);
   } else {
     relocate(filter, join);
   }
 }
 public long getCardinality(Join join, BindingSet bindings) {
   long card1 = getCardinality(join.getLeftArg(), bindings);
   long card2 = getCardinality(join.getRightArg(), bindings);
   double sel = 0.5;
   return (long) (card1 * card2 * sel);
 }