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 + " )" ; } } ; }
Create a sequence of nodes that returns at most the supplied number of rows .