Skip to content

Commit

Permalink
[optimization] Make fn:subsequence lazily evaluated
Browse files Browse the repository at this point in the history
  • Loading branch information
adamretter committed Sep 2, 2018
1 parent cc0a5bf commit c262649
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 37 deletions.
38 changes: 1 addition & 37 deletions src/org/exist/xquery/functions/fn/FunSubSequence.java
Expand Up @@ -133,43 +133,7 @@ and position() lt fn:round($startingLoc) + fn:round($length)]
fromInclusive = startArg;
}

// holds the intermittent result
Sequence tmp = Sequence.EMPTY_SEQUENCE;

long position = 1;
final SequenceIterator iterator = seq.iterate();
if (position != fromInclusive) {
// move to start (i.e. fromInclusive)
if (iterator.skip(fromInclusive - position) > -1) {
position = fromInclusive;
} else {
// SequenceIterator does not support skipping, we have to iterate through each item :-/
for (; position < fromInclusive; position++) {
iterator.nextItem();
}
}
}

// copy from start to end
while (iterator.hasNext() && position < toExclusive) {
final Item item = iterator.nextItem();

// lazily initialize tmp
if (tmp == Sequence.EMPTY_SEQUENCE) {
if (seq instanceof NodeSet) {
tmp = new ExtArrayNodeSet();
((ExtArrayNodeSet) tmp).keepUnOrdered(unordered);
} else {
tmp = new ValueSequence();
((ValueSequence) tmp).keepUnOrdered(unordered);
}
}

tmp.add(item);
position++;
}

result = tmp;
result = new SubSequence(fromInclusive, toExclusive, seq);
}

if (context.getProfiler().isEnabled()) {
Expand Down
12 changes: 12 additions & 0 deletions test/src/org/exist/xquery/functions/fn/FunSubSequenceTest.java
Expand Up @@ -156,6 +156,18 @@ public void smallPartOfLargeRange_arity3() throws XMLDBException {
assertEquals("(2999999995,2999999996,2999999997,2999999998,2999999999)", asSequenceStr(result));
}

@Test
public void largeRange_arity2() throws XMLDBException {
final ResourceSet result = existEmbeddedServer.executeQuery("fn:count(fn:subsequence((1 to 3000000000), -2147483649))");
assertEquals("(3000000000)", asSequenceStr(result));
}

@Test
public void largeRange_arity3() throws XMLDBException {
final ResourceSet result = existEmbeddedServer.executeQuery("fn:count(fn:subsequence((1 to 3000000000), 1, 3000000000))");
assertEquals("(3000000000)", asSequenceStr(result));
}

private static String asSequenceStr(final ResourceSet result) throws XMLDBException {
final StringBuilder builder = new StringBuilder();
builder.append('(');
Expand Down

0 comments on commit c262649

Please sign in to comment.