docs: public static NodeSequence limit( final NodeSequence sequence,
                                        final long maxRows ) {
          if (sequence == null) return emptySequence(0);
          if (maxRows <= 0) return emptySequence(sequence.width());
          if (sequence.isEmpty()) return sequence;
          return new NodeSequence() {
              private LimitBatch lastLimitBatch = null;
              protected long rowsRemaining = maxRows;
  
              @Override
              public long getRowCount() {
                  long count = sequence.getRowCount();
                  if (count < 0L) return -1;
                  return count < maxRows ? count : maxRows;
              }
  
              @Override
              public int width() {
                  return sequence.width();
              }
  
              @Override
              public boolean isEmpty() {
                  return false;
              }
  
              @Override
              public Batch nextBatch() {
                  if (rowsRemaining <= 0) return null;
                  if (lastLimitBatch != null) {
                      long rowsUsed = lastLimitBatch.rowsUsed();
                      if (rowsUsed < rowsRemaining) {
                          rowsRemaining -= rowsUsed;
                      } else {
                          return null; 
                      }
                  }
                  final Batch next = sequence.nextBatch();
                  if (next == null) return null;
                  long size = next.rowCount();
                  boolean sizeKnown = false;
                  if (size >= 0) {
                      // The size is known ...
                      sizeKnown = true;
                      if (size <= rowsRemaining) {
                          // The whole batch can be returned ...
                          rowsRemaining -= size;
                          return next;
                      }
                      // Only the first part of this batch is okay ...
                      assert size > rowsRemaining;
                      // just continue ...
                  }
                  // The size is not known or larger than rowsRemaining, so we return a batch that exposes only the number we need
                  long limit = rowsRemaining;
                  lastLimitBatch = new LimitBatch(next, limit, sizeKnown);
                  return lastLimitBatch;
              }
  
              @Override
              public void close() {
                  sequence.close();
              }
  
              @Override
              public String toString() {
                  return "(limit " + maxRows + " " + sequence + " )";
              }
          };
      }