Skip to content

Commit 5a1586b

Browse files
committed
[bugfix] Correct type conversions for fields in the Lucene Full Text Index
The issues were previously introduced in eXist-db/exist#4253 and eXist-db/exist#4541 Closes eXist-db/exist#5193
1 parent 01c2fac commit 5a1586b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+5093
-479
lines changed

exist-core/pom.xml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,8 @@
742742
<include>src/test/java/org/exist/http/urlrewrite/RedirectTest.java</include>
743743
<include>src/main/java/org/exist/storage/io/AbstractVariableByteOutput.java</include>
744744
<include>src/main/java/org/exist/storage/io/VariableByteArrayOutputStream.java</include>
745+
<include>src/main/java/org/exist/storage/io/VariableByteBufferInput.java</include>
746+
<include>src/main/java/org/exist/storage/io/VariableByteBufferOutput.java</include>
745747
<include>src/main/java/org/exist/storage/io/VariableByteFilterInputStream.java</include>
746748
<include>src/main/java/org/exist/storage/io/VariableByteFilterOutputStream.java</include>
747749
<include>src/main/java/org/exist/storage/io/VariableByteOutput.java</include>
@@ -838,6 +840,7 @@
838840
<include>src/main/java/org/exist/config/ConfigurationImpl.java</include>
839841
<include>src/main/java/org/exist/config/Configurator.java</include>
840842
<include>src/main/java/org/exist/dom/NodeListImpl.java</include>
843+
<include>src/main/java/org/exist/dom/QName.java</include>
841844
<exclude>src/main/java/org/exist/dom/memtree/AbstractCharacterData.java</exclude>
842845
<include>src/main/java/org/exist/dom/memtree/AttrImpl.java</include>
843846
<include>src/main/java/org/exist/dom/memtree/DocumentImpl.java</include>
@@ -1052,7 +1055,28 @@
10521055
<include>src/main/java/org/exist/xquery/util/ExpressionDumper.java</include>
10531056
<include>src/main/java/org/exist/xquery/util/SerializerUtils.java</include>
10541057
<include>src/main/java/org/exist/xquery/value/AbstractDateTimeValue.java</include>
1058+
<include>src/main/java/org/exist/xquery/value/AnyURIValue.java</include>
10551059
<include>src/test/java/org/exist/xquery/value/Base64BinaryValueTypeTest.java</include>
1060+
<include>src/main/java/org/exist/xquery/value/BinaryValue.java</include>
1061+
<include>src/main/java/org/exist/xquery/value/BooleanValue.java</include>
1062+
<include>src/main/java/org/exist/xquery/value/DateTimeStampValue.java</include>
1063+
<include>src/main/java/org/exist/xquery/value/DateTimeValue.java</include>
1064+
<include>src/main/java/org/exist/xquery/value/DateValue.java</include>
1065+
<include>src/main/java/org/exist/xquery/value/DayTimeDurationValue.java</include>
1066+
<include>src/main/java/org/exist/xquery/value/DecimalValue.java</include>
1067+
<include>src/main/java/org/exist/xquery/value/DoubleValue.java</include>
1068+
<include>src/main/java/org/exist/xquery/value/DurationValue.java</include>
1069+
<include>src/main/java/org/exist/xquery/value/FloatValue.java</include>
1070+
<include>src/main/java/org/exist/xquery/value/GDayValue.java</include>
1071+
<include>src/main/java/org/exist/xquery/value/GMonthDayValue.java</include>
1072+
<include>src/main/java/org/exist/xquery/value/GMonthValue.java</include>
1073+
<include>src/main/java/org/exist/xquery/value/GYearMonthValue.java</include>
1074+
<include>src/main/java/org/exist/xquery/value/GYearValue.java</include>
1075+
<include>src/main/java/org/exist/xquery/value/IntegerValue.java</include>
1076+
<include>src/main/java/org/exist/xquery/value/QNameValue.java</include>
1077+
<include>src/main/java/org/exist/xquery/value/StringValue.java</include>
1078+
<include>src/main/java/org/exist/xquery/value/TimeValue.java</include>
1079+
<include>src/main/java/org/exist/xquery/value/YearMonthDurationValue.java</include>
10561080
<include>src/main/java/org/exist/xquery/value/SequenceType.java</include>
10571081
<include>src/main/java/org/exist/xquery/value/TimeUtils.java</include>
10581082
<include>src/main/java/org/exist/xquery/value/Type.java</include>
@@ -1152,6 +1176,7 @@
11521176
<exclude>src/main/java/org/exist/config/ConfigurationImpl.java</exclude>
11531177
<exclude>src/main/java/org/exist/config/Configurator.java</exclude>
11541178
<exclude>src/main/java/org/exist/dom/NodeListImpl.java</exclude>
1179+
<exclude>src/main/java/org/exist/dom/QName.java</exclude>
11551180
<exclude>src/main/java/org/exist/dom/memtree/AbstractCharacterData.java</exclude>
11561181
<exclude>src/main/java/org/exist/dom/memtree/AttrImpl.java</exclude>
11571182
<exclude>src/main/java/org/exist/dom/memtree/DocumentImpl.java</exclude>
@@ -1287,6 +1312,8 @@
12871312
<exclude>src/main/java/org/exist/storage/io/AbstractVariableByteOutput.java</exclude>
12881313
<exclude>src/main/java/org/exist/storage/io/VariableByteArrayInput.java</exclude>
12891314
<exclude>src/main/java/org/exist/storage/io/VariableByteArrayOutputStream.java</exclude>
1315+
<exclude>src/main/java/org/exist/storage/io/VariableByteBufferInput.java</exclude>
1316+
<exclude>src/main/java/org/exist/storage/io/VariableByteBufferOutput.java</exclude>
12901317
<exclude>src/main/java/org/exist/storage/io/VariableByteFilterInputStream.java</exclude>
12911318
<exclude>src/main/java/org/exist/storage/io/VariableByteFilterOutputStream.java</exclude>
12921319
<exclude>src/main/java/org/exist/storage/io/VariableByteInput.java</exclude>
@@ -1470,19 +1497,40 @@
14701497
<exclude>src/main/java/org/exist/xquery/util/SerializerUtils.java</exclude>
14711498
<exclude>src/test/java/org/exist/xquery/util/URIUtilsTest.java</exclude>
14721499
<exclude>src/main/java/org/exist/xquery/value/AbstractDateTimeValue.java</exclude>
1500+
<exclude>src/main/java/org/exist/xquery/value/AnyURIValue.java</exclude>
14731501
<exclude>src/main/java/org/exist/xquery/value/ArrayListValueSequence.java</exclude>
14741502
<exclude>src/main/java/org/exist/xquery/value/AtomicValueComparator.java</exclude>
14751503
<exclude>src/test/java/org/exist/xquery/value/Base64BinaryValueTypeTest.java</exclude>
14761504
<exclude>src/test/java/org/exist/xquery/value/BifurcanMapTest.java</exclude>
1505+
<exclude>src/main/java/org/exist/xquery/value/BinaryValue.java</exclude>
1506+
<exclude>src/main/java/org/exist/xquery/value/BooleanValue.java</exclude>
1507+
<exclude>src/main/java/org/exist/xquery/value/DateTimeStampValue.java</exclude>
14771508
<exclude>src/test/java/org/exist/xquery/value/DateTimeTypesTest.java</exclude>
1509+
<exclude>src/main/java/org/exist/xquery/value/DateTimeValue.java</exclude>
1510+
<exclude>src/main/java/org/exist/xquery/value/DateValue.java</exclude>
1511+
<exclude>src/main/java/org/exist/xquery/value/DayTimeDurationValue.java</exclude>
1512+
<exclude>src/main/java/org/exist/xquery/value/DecimalValue.java</exclude>
1513+
<exclude>src/main/java/org/exist/xquery/value/DoubleValue.java</exclude>
1514+
<exclude>src/main/java/org/exist/xquery/value/DurationValue.java</exclude>
1515+
<exclude>src/main/java/org/exist/xquery/value/FloatValue.java</exclude>
1516+
<exclude>src/main/java/org/exist/xquery/value/GDayValue.java</exclude>
1517+
<exclude>src/main/java/org/exist/xquery/value/GMonthDayValue.java</exclude>
1518+
<exclude>src/main/java/org/exist/xquery/value/GMonthValue.java</exclude>
1519+
<exclude>src/main/java/org/exist/xquery/value/GYearMonthValue.java</exclude>
1520+
<exclude>src/main/java/org/exist/xquery/value/GYearValue.java</exclude>
1521+
<exclude>src/main/java/org/exist/xquery/value/IntegerValue.java</exclude>
14781522
<exclude>src/main/java/org/exist/xquery/value/ItemComparator.java</exclude>
1523+
<exclude>src/main/java/org/exist/xquery/value/QNameValue.java</exclude>
14791524
<exclude>src/main/java/org/exist/xquery/value/SequenceComparator.java</exclude>
14801525
<exclude>src/main/java/org/exist/xquery/value/SequenceType.java</exclude>
1526+
<exclude>src/main/java/org/exist/xquery/value/StringValue.java</exclude>
14811527
<exclude>src/main/java/org/exist/xquery/value/SubSequence.java</exclude>
14821528
<exclude>src/test/java/org/exist/xquery/value/SubSequenceRangeTest.java</exclude>
14831529
<exclude>src/test/java/org/exist/xquery/value/SubSequenceTest.java</exclude>
1530+
<exclude>src/main/java/org/exist/xquery/value/TimeValue.java</exclude>
14841531
<exclude>src/main/java/org/exist/xquery/value/TimeUtils.java</exclude>
14851532
<exclude>src/main/java/org/exist/xquery/value/Type.java</exclude>
1533+
<exclude>src/main/java/org/exist/xquery/value/YearMonthDurationValue.java</exclude>
14861534
<exclude>src/main/java/org/exist/xslt/EXistURIResolver.java</exclude>
14871535
<exclude>src/main/java/org/exist/xslt/XsltURIResolverHelper.java</exclude>
14881536
<exclude>src/test/java/org/exist/xupdate/RemoveAppendTest.java</exclude>

exist-core/src/main/java/org/exist/dom/QName.java

Lines changed: 99 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,28 @@
11
/*
2+
* Elemental
3+
* Copyright (C) 2024, Evolved Binary Ltd
4+
*
5+
6+
* https://www.evolvedbinary.com | https://www.elemental.xyz
7+
*
8+
* This library is free software; you can redistribute it and/or
9+
* modify it under the terms of the GNU Lesser General Public
10+
* License as published by the Free Software Foundation; version 2.1.
11+
*
12+
* This library is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
* Lesser General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public
18+
* License along with this library; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20+
*
21+
* NOTE: Parts of this file contain code from 'The eXist-db Authors'.
22+
* The original license header is included below.
23+
*
24+
* =====================================================================
25+
*
226
* eXist-db Open Source Native XML Database
327
* Copyright (C) 2001 The eXist-db Authors
428
*
@@ -26,16 +50,19 @@
2650
import org.exist.util.XMLNames;
2751
import org.exist.xquery.Constants;
2852

53+
import javax.annotation.Nullable;
2954
import javax.xml.XMLConstants;
3055
import java.util.regex.Matcher;
3156
import java.util.regex.Pattern;
3257

3358
import static org.exist.dom.QName.Validity.*;
59+
import static org.exist.util.StringUtil.isNullOrEmpty;
3460

3561
/**
3662
* Represents a QName, consisting of a local name, a namespace URI and a prefix.
3763
*
3864
* @author <a href="mailto:[email protected]">Wolfgang</a>
65+
* @author <a href="mailto:[email protected]">Adam Retter</a>
3966
*/
4067
public class QName implements Comparable<QName> {
4168

@@ -134,7 +161,18 @@ public byte getNameType() {
134161
* @return the string representation of this qualified name.
135162
* */
136163
public String getStringValue() {
137-
return getStringRepresentation(false);
164+
return getStringRepresentation(false, false);
165+
}
166+
167+
/**
168+
* Get an extended string representation of this qualified name.
169+
*
170+
* Will be of the format `local-name`, `{namespace}local-name`, or `{namespace}prefix:local-name`.
171+
*
172+
* @return the string representation of this qualified name.
173+
*/
174+
public String getExtendedStringValue() {
175+
return getStringRepresentation(false, true);
138176
}
139177

140178
/**
@@ -146,23 +184,32 @@ public String getStringValue() {
146184
*/
147185
@Override
148186
public String toString() {
149-
return getStringRepresentation(true);
187+
return getStringRepresentation(true, false);
150188
}
151189

152190
/**
153191
* Get a string representation of this qualified name.
154192
*
155193
* @param showNsWithoutPrefix true if the namespace should be shown even when there is no prefix, false otherwise.
156-
* When shown, it will be output using Clark notation, e.g. `{http://namespace}local-name`.
194+
* When shown, it will be output using Clark notation, e.g. `{namespace}local-name`.
195+
*
196+
* @param extended true if the namespace and prefix should be shown, requires showNsWithoutPrefix == false.
157197
*
158198
* @return the string representation of this qualified name.
159199
*/
160-
private String getStringRepresentation(final boolean showNsWithoutPrefix) {
200+
private String getStringRepresentation(final boolean showNsWithoutPrefix, final boolean extended) {
161201
if (prefix != null && !prefix.isEmpty()) {
162-
return prefix + COLON + localPart;
163-
} else if (showNsWithoutPrefix && namespaceURI != null && !XMLConstants.NULL_NS_URI.equals(namespaceURI)) {
202+
if (extended) {
203+
return LEFT_BRACE + namespaceURI + RIGHT_BRACE + prefix + COLON + localPart;
204+
} else {
205+
return prefix + COLON + localPart;
206+
}
207+
}
208+
209+
if (showNsWithoutPrefix && namespaceURI != null && !XMLConstants.NULL_NS_URI.equals(namespaceURI)) {
164210
return LEFT_BRACE + namespaceURI + RIGHT_BRACE + localPart;
165211
}
212+
166213
return localPart;
167214
}
168215

@@ -330,6 +377,52 @@ public static QName parse(final String namespaceURI, final String qname) throws
330377
return new QName(qname.substring(p + 1), namespaceURI, qname.substring(0, p));
331378
}
332379

380+
/**
381+
* Extract a QName from a namespace and qualified name string.
382+
*
383+
* @param extendedStringValue a string representation as produced by {@link #getExtendedStringValue()}, i.e.: `local-name`, `{namespace}local-name`, or `{namespace}prefix:local-name`.
384+
* @return The QName
385+
* @throws IllegalQNameException if the qname component is invalid
386+
*/
387+
public static QName parse(String extendedStringValue) throws IllegalQNameException {
388+
if (isNullOrEmpty(extendedStringValue)) {
389+
throw new IllegalQNameException(ILLEGAL_FORMAT.val, "Illegal extended string QName is empty");
390+
}
391+
392+
final String namespaceUri;
393+
if (extendedStringValue.charAt(0) == LEFT_BRACE) {
394+
final int idxNsEnd = extendedStringValue.indexOf(RIGHT_BRACE);
395+
if (idxNsEnd == Constants.STRING_NOT_FOUND) {
396+
throw new IllegalQNameException(ILLEGAL_FORMAT.val, "Illegal extended string QName, missing right brace: '" + extendedStringValue + "'");
397+
}
398+
namespaceUri = extendedStringValue.substring(1, idxNsEnd);
399+
extendedStringValue = extendedStringValue.substring(idxNsEnd + 1);
400+
} else if (extendedStringValue.indexOf(RIGHT_BRACE) != Constants.STRING_NOT_FOUND) {
401+
throw new IllegalQNameException(ILLEGAL_FORMAT.val, "Illegal extended string QName, missing left brace: '" + extendedStringValue + "'");
402+
} else {
403+
namespaceUri = XMLConstants.NULL_NS_URI;
404+
}
405+
406+
@Nullable final String prefix;
407+
final int idxColon = extendedStringValue.indexOf(COLON);
408+
if (idxColon == Constants.STRING_NOT_FOUND) {
409+
prefix = null;
410+
} else {
411+
prefix = extendedStringValue.substring(0, idxColon);
412+
if (!XMLNames.isNCName(prefix)) {
413+
throw new IllegalQNameException(INVALID_PREFIX.val, "Illegal extended string QName, invalid prefix: '" + extendedStringValue + "'");
414+
}
415+
extendedStringValue = extendedStringValue.substring(idxColon + 1);
416+
}
417+
418+
final String localPart = extendedStringValue;
419+
if (!XMLNames.isNCName(localPart)) {
420+
throw new IllegalQNameException(INVALID_LOCAL_PART.val, "Illegal extended string QName, invalid prefix: '" + extendedStringValue + "'");
421+
}
422+
423+
return new QName(localPart, namespaceUri, prefix);
424+
}
425+
333426
/**
334427
* Parses the given string into a QName. The method uses context to look up
335428
* a namespace URI for an existing prefix.

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
import org.exist.xquery.value.StringValue;
7676
import org.w3c.dom.*;
7777

78+
import javax.annotation.Nullable;
7879
import javax.xml.XMLConstants;
7980
import javax.xml.stream.XMLStreamConstants;
8081
import javax.xml.stream.XMLStreamException;
@@ -1384,6 +1385,10 @@ public String getNamespaceForPrefix(final String prefix) {
13841385
return namespaceMappings.get(prefix);
13851386
}
13861387

1388+
public @Nullable Map<String, String> getNamespaceMappings() {
1389+
return namespaceMappings;
1390+
}
1391+
13871392
/**
13881393
* @see java.lang.Object#toString()
13891394
*/

exist-core/src/main/java/org/exist/storage/index/BFile.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@
8080

8181
import java.io.EOFException;
8282
import java.io.IOException;
83+
import java.math.BigDecimal;
84+
import java.math.BigInteger;
85+
import java.math.MathContext;
8386
import java.nio.file.Path;
8487
import java.text.NumberFormat;
8588
import java.util.ArrayList;
@@ -2364,6 +2367,48 @@ public long readFixedLong() throws IOException {
23642367
return r;
23652368
}
23662369

2370+
@Override
2371+
public BigInteger readBigInteger() throws IOException {
2372+
final int dataLength = readInt();
2373+
final byte[] data = new byte[dataLength];
2374+
read(data);
2375+
2376+
return new BigInteger(data);
2377+
}
2378+
2379+
@Override
2380+
public BigInteger readFixedBigInteger() throws IOException {
2381+
final int dataLength = readFixedInt();
2382+
final byte[] data = new byte[dataLength];
2383+
read(data);
2384+
2385+
return new BigInteger(data);
2386+
}
2387+
2388+
@Override
2389+
public BigDecimal readBigDecimal() throws IOException {
2390+
final int scale = readInt();
2391+
final int precision = readInt();
2392+
final int dataLength = readInt();
2393+
final byte[] data = new byte[dataLength];
2394+
read(data);
2395+
2396+
final MathContext mathContext = new java.math.MathContext(precision);
2397+
return new BigDecimal(new BigInteger(data), scale, mathContext);
2398+
}
2399+
2400+
@Override
2401+
public BigDecimal readFixedBigDecimal() throws IOException {
2402+
final int scale = readFixedInt();
2403+
final int precision = readFixedInt();
2404+
final int dataLength = readFixedInt();
2405+
final byte[] data = new byte[dataLength];
2406+
read(data);
2407+
2408+
final MathContext mathContext = new java.math.MathContext(precision);
2409+
return new BigDecimal(new BigInteger(data), scale, mathContext);
2410+
}
2411+
23672412
@Override
23682413
public final void skip(final int count) throws IOException {
23692414
for (int i = 0; i < count; i++) {

0 commit comments

Comments
 (0)