@Override
 public Row next() {
   if (TAP_NEXT_ENABLED) {
     TAP_NEXT.in();
   }
   try {
     if (CURSOR_LIFECYCLE_ENABLED) {
       CursorLifecycle.checkIdleOrActive(this);
     }
     checkQueryCancelation();
     Row row;
     while (skipLeft > 0) {
       if ((row = input.next()) == null) {
         skipLeft = 0;
         limitLeft = -1;
         setIdle();
         if (LOG_EXECUTION) {
           LOG.debug("Limit_Default: skipLeft until complete yield null");
         }
         return null;
       }
       skipLeft--;
     }
     if (limitLeft < 0) {
       setIdle();
       if (LOG_EXECUTION) {
         LOG.debug("Limit_Default: limitLeft < 0, yield null");
       }
       return null;
     }
     if (limitLeft == 0) {
       setIdle();
       if (LOG_EXECUTION) {
         LOG.debug("Limit_Default: limitLeft == 0, yield null");
       }
       return null;
     }
     if ((row = input.next()) == null) {
       limitLeft = -1;
       setIdle();
       if (LOG_EXECUTION) {
         LOG.debug("Limit_Default: yield null");
       }
       return null;
     }
     --limitLeft;
     if (LOG_EXECUTION) {
       LOG.debug("Limit_Default: yield {}", row);
     }
     return row;
   } finally {
     if (TAP_NEXT_ENABLED) {
       TAP_NEXT.out();
     }
   }
 }
 private boolean rowReallyHasMatch(Row row) {
   // bindingPosition is used to hold onto a row for use during the evaluation of expressions
   // during onPositiveCursor.open(). This is somewhat sleazy, but the alternative is to
   // complicate the Select_BloomFilter API, requiring the caller to specify another binding
   // position.
   // It is safe to reuse the binding position in this way because the filter is extracted and
   // stored
   // in a field during open(), while the use of the binding position for use in the onPositive
   // lookup
   // occurs during next().
   if (LOG_EXECUTION) {
     LOG.debug("Select_BloomFilter: candidate {}", row);
   }
   TAP_CHECK.in();
   try {
     bindings.setRow(bindingPosition, row);
     onPositiveBindingsCursor.reset(bindings);
     onPositiveCursor.openTopLevel();
     try {
       return onPositiveCursor.next() != null;
     } finally {
       onPositiveCursor.closeTopLevel();
       bindings.setRow(bindingPosition, null);
     }
   } finally {
     TAP_CHECK.out();
   }
 }
 @Override
 public Row next() {
   if (TAP_NEXT_ENABLED) {
     TAP_NEXT.in();
   }
   try {
     if (CURSOR_LIFECYCLE_ENABLED) {
       CursorLifecycle.checkIdleOrActive(this);
     }
     Row row;
     do {
       row = inputCursor.next();
       if (row == null) {
         close();
       } else if (!filter.maybePresent(hashProjectedRow(row)) || !rowReallyHasMatch(row)) {
         row = null;
       }
     } while (!idle && row == null);
     if (LOG_EXECUTION) {
       LOG.debug("Select_BloomFilter: yield {}", row);
     }
     return row;
   } finally {
     if (TAP_NEXT_ENABLED) {
       TAP_NEXT.out();
     }
   }
 }
 @Override
 protected Row nextInputRow() {
   BloomFilter filter = baseBindings.getBloomFilter(bindingPosition);
   while (true) {
     Row row = input.next();
     if (row == null) {
       return row;
     }
     if (filter.maybePresent(hashProjectedRow(row))) {
       if (ExecutionBase.LOG_EXECUTION) {
         LOG.debug("Select_BloomFilter: candidate {}", row);
       }
       return row;
     }
   }
 }