Skip to content

Commit d3a7fbc

Browse files
authored
Merge pull request #4662 from evolvedbinary/hotfix/too-eager-destroy
Fix issues with binary files being closed whilst they are still needed
2 parents 6a48b81 + 8259d08 commit d3a7fbc

File tree

8 files changed

+331
-18
lines changed

8 files changed

+331
-18
lines changed

exist-core/pom.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,7 @@
721721
<exclude>src/main/java/org/exist/xquery/value/SubSequence.java</exclude>
722722
<exclude>src/test/java/org/exist/xquery/value/SubSequenceRangeTest.java</exclude>
723723
<exclude>src/test/java/org/exist/xquery/value/SubSequenceTest.java</exclude>
724+
<exclude>src/test/xquery/binary-value.xqm</exclude>
724725

725726
<!--
726727
Derivative work licensed under dbXML 1.0 and LGPL 2.1
@@ -870,6 +871,7 @@ The original license statement is also included below.]]></preamble>
870871
<include>src/main/java/org/exist/xquery/value/SubSequence.java</include>
871872
<include>src/test/java/org/exist/xquery/value/SubSequenceRangeTest.java</include>
872873
<include>src/test/java/org/exist/xquery/value/SubSequenceTest.java</include>
874+
<include>src/test/xquery/binary-value.xqm</include>
873875
</includes>
874876

875877
</licenseSet>

exist-core/src/main/java/org/exist/dom/persistent/NodeProxy.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1168,11 +1168,11 @@ public boolean getProcessInReverseOrder() {
11681168
@Override
11691169
public NodeSet getParents(final int contextId) {
11701170
final NodeId pid = nodeId.getParentId();
1171-
if(pid == null || pid == NodeId.DOCUMENT_NODE) {
1171+
if (pid == null) {
11721172
return NodeSet.EMPTY_SET;
11731173
}
11741174

1175-
final NodeProxy parent = new NodeProxy(expression, doc, pid, Node.ELEMENT_NODE);
1175+
final NodeProxy parent = new NodeProxy(expression, doc, pid, pid == NodeId.DOCUMENT_NODE ? Node.DOCUMENT_NODE : Node.ELEMENT_NODE);
11761176
if(contextId != Expression.NO_CONTEXT_ID) {
11771177
parent.addContextNode(contextId, this);
11781178
} else {

exist-core/src/main/java/org/exist/xquery/Predicate.java

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.exist.xquery.value.Type;
3838
import org.exist.xquery.value.ValueSequence;
3939

40+
import javax.annotation.Nullable;
4041
import java.util.Set;
4142
import java.util.TreeSet;
4243

@@ -164,7 +165,7 @@ public Sequence evalPredicate(final Sequence outerSequence,
164165

165166
final Tuple2<ExecutionMode, Sequence> recomputed = recomputeExecutionMode(contextSequence, inner);
166167
final ExecutionMode recomputedExecutionMode = recomputed._1;
167-
Sequence innerSeq = recomputed._2;
168+
@Nullable Sequence innerSeq = recomputed._2;
168169

169170
switch (recomputedExecutionMode) {
170171
case NODE:
@@ -564,25 +565,57 @@ private Sequence selectByPosition(final Sequence outerSequence,
564565
Type.NODE) && (mode == Constants.ANCESTOR_AXIS ||
565566
mode == Constants.ANCESTOR_SELF_AXIS || mode == Constants.PARENT_AXIS ||
566567
mode == Constants.PRECEDING_AXIS || mode == Constants.PRECEDING_SIBLING_AXIS);
567-
final Set<NumericValue> set = new TreeSet<>();
568-
final ValueSequence result = new ValueSequence();
569-
for (final SequenceIterator i = innerSeq.iterate(); i.hasNext(); ) {
570-
final NumericValue v = (NumericValue) i.nextItem();
568+
569+
Sequence result = Sequence.EMPTY_SEQUENCE;
570+
if (innerSeq.hasOne()) {
571+
// optimise for single position lookup
572+
final NumericValue v = (NumericValue) innerSeq.itemAt(0);
571573
// Non integers return... nothing, not even an error !
572-
if (!v.hasFractionalPart() && !v.isZero()) {
573-
final int pos = (reverseAxis ? contextSequence.getItemCount()
574-
- v.getInt() : v.getInt() - 1);
574+
if (isNonZeroInteger(v)) {
575+
final int pos = calculatePos(reverseAxis, contextSequence, v);
575576
// Other positions are ignored
576-
if (pos >= 0 && pos < contextSequence.getItemCount() && !set.contains(v)) {
577-
result.add(contextSequence.itemAt(pos));
578-
set.add(v);
577+
if (withinBounds(contextSequence, pos)) {
578+
result = (Sequence) contextSequence.itemAt(pos);
579+
}
580+
}
581+
} else {
582+
// multi-position lookup
583+
Set<NumericValue> set = null;
584+
for (final SequenceIterator i = innerSeq.iterate(); i.hasNext(); ) {
585+
final NumericValue v = (NumericValue) i.nextItem();
586+
// Non integers return... nothing, not even an error !
587+
if (isNonZeroInteger(v)) {
588+
final int pos = calculatePos(reverseAxis, contextSequence, v);
589+
// Other positions are ignored
590+
if (withinBounds(contextSequence, pos) && (set == null || !set.contains(v))) {
591+
if (result == Sequence.EMPTY_SEQUENCE) {
592+
result = new ValueSequence();
593+
}
594+
result.add(contextSequence.itemAt(pos));
595+
if (set == null) {
596+
set = new TreeSet<>();
597+
}
598+
set.add(v);
599+
}
579600
}
580601
}
581602
}
582603
return result;
583604
}
584605
}
585606

607+
private static boolean isNonZeroInteger(final NumericValue v) {
608+
return !v.hasFractionalPart() && !v.isZero();
609+
}
610+
611+
private static int calculatePos(final boolean reverseAxis, final Sequence contextSequence, final NumericValue v) throws XPathException {
612+
return (reverseAxis ? contextSequence.getItemCount() - v.getInt() : v.getInt() - 1);
613+
}
614+
615+
private static boolean withinBounds(final Sequence contextSequence, final int pos) {
616+
return pos >= 0 && pos < contextSequence.getItemCount();
617+
}
618+
586619
@Override
587620
public void setContextDocSet(final DocumentSet contextSet) {
588621
super.setContextDocSet(contextSet);

exist-core/src/main/java/org/exist/xquery/functions/array/ArrayType.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,27 @@ public boolean contains(final Item item) {
421421
return false;
422422
}
423423

424+
@Override
425+
public String toString() {
426+
final StringBuilder builder = new StringBuilder();
427+
builder.append('[');
428+
if (vector.length() > 0) {
429+
builder.append(' ');
430+
}
431+
for (int i = 0; i < vector.length(); i++) {
432+
final Sequence value = vector.nth(i);
433+
builder.append(value.toString());
434+
if (i < vector.length() - 1) {
435+
builder.append(", ");
436+
}
437+
}
438+
if (vector.length() > 0) {
439+
builder.append(' ');
440+
}
441+
builder.append(']');
442+
return builder.toString();
443+
}
444+
424445
/**
425446
* The accessor function which will be evaluated if the map is called
426447
* as a function item.

exist-core/src/main/java/org/exist/xquery/functions/map/MapType.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ public boolean contains(AtomicValue key) {
283283
public boolean containsReference(final Item item) {
284284
for (final Iterator<Sequence> it = map.values().iterator(); it.hasNext();) {
285285
final Sequence value = it.next();
286-
if (value == item) {
286+
if (value == item || value.containsReference(item)) {
287287
return true;
288288
}
289289
}
@@ -294,7 +294,7 @@ public boolean containsReference(final Item item) {
294294
public boolean contains(final Item item) {
295295
for (final Iterator<Sequence> it = map.values().iterator(); it.hasNext();) {
296296
final Sequence value = it.next();
297-
if (value.equals(item)) {
297+
if (value.equals(item) || value.contains(item)) {
298298
return true;
299299
}
300300
}

exist-core/src/main/java/org/exist/xquery/value/BinaryValue.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ public <T> T toJavaObject(Class<T> target) throws XPathException {
155155
return (T) baos.toByteArray();
156156
} catch (final IOException ioe) {
157157
LOG.error("Unable to Stream BinaryValue to byte[]: {}", ioe.getMessage(), ioe);
158+
throw new XPathException(getExpression(), "Unable to Stream BinaryValue to byte[]: " + ioe.getMessage(), ioe);
158159
}
159-
160160
}
161161

162162
throw new XPathException(getExpression(), "Cannot convert value of type " + Type.getTypeName(getType()) + " to Java object of type " + target.getName());

0 commit comments

Comments
 (0)