Skip to content

Commit 9b3ab7a

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 e8d7680 commit 9b3ab7a

46 files changed

Lines changed: 5080 additions & 527 deletions

Some content is hidden

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

exist-core/pom.xml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,8 @@
692692
<include>src/main/java/org/exist/dom/memtree/reference/TextReferenceImpl.java</include>
693693
<include>src/main/java/org/exist/storage/io/AbstractVariableByteOutput.java</include>
694694
<include>src/main/java/org/exist/storage/io/VariableByteArrayOutputStream.java</include>
695+
<include>src/main/java/org/exist/storage/io/VariableByteBufferInput.java</include>
696+
<include>src/main/java/org/exist/storage/io/VariableByteBufferOutput.java</include>
695697
<include>src/main/java/org/exist/storage/io/VariableByteFilterInputStream.java</include>
696698
<include>src/main/java/org/exist/storage/io/VariableByteFilterOutputStream.java</include>
697699
<include>src/main/java/org/exist/storage/io/VariableByteOutput.java</include>
@@ -776,6 +778,7 @@
776778
<include>src/main/java/org/exist/collections/triggers/XQueryStartupTrigger.java</include>
777779
<include>src/main/java/org/exist/config/Configuration.java</include>
778780
<include>src/main/java/org/exist/config/ConfigurationImpl.java</include>
781+
<include>src/main/java/org/exist/dom/QName.java</include>
779782
<include>src/main/java/org/exist/dom/memtree/AttrImpl.java</include>
780783
<include>src/main/java/org/exist/dom/memtree/DocumentImpl.java</include>
781784
<include>src/main/java/org/exist/dom/memtree/DOMIndexer.java</include>
@@ -938,7 +941,28 @@
938941
<include>src/test/java/org/exist/xquery/update/UpdateReplaceTest.java</include>
939942
<include>src/main/java/org/exist/xquery/util/SerializerUtils.java</include>
940943
<include>src/main/java/org/exist/xquery/value/AbstractDateTimeValue.java</include>
944+
<include>src/main/java/org/exist/xquery/value/AnyURIValue.java</include>
941945
<include>src/test/java/org/exist/xquery/value/Base64BinaryValueTypeTest.java</include>
946+
<include>src/main/java/org/exist/xquery/value/BinaryValue.java</include>
947+
<include>src/main/java/org/exist/xquery/value/BooleanValue.java</include>
948+
<include>src/main/java/org/exist/xquery/value/DateTimeStampValue.java</include>
949+
<include>src/main/java/org/exist/xquery/value/DateTimeValue.java</include>
950+
<include>src/main/java/org/exist/xquery/value/DateValue.java</include>
951+
<include>src/main/java/org/exist/xquery/value/DayTimeDurationValue.java</include>
952+
<include>src/main/java/org/exist/xquery/value/DecimalValue.java</include>
953+
<include>src/main/java/org/exist/xquery/value/DoubleValue.java</include>
954+
<include>src/main/java/org/exist/xquery/value/DurationValue.java</include>
955+
<include>src/main/java/org/exist/xquery/value/FloatValue.java</include>
956+
<include>src/main/java/org/exist/xquery/value/GDayValue.java</include>
957+
<include>src/main/java/org/exist/xquery/value/GMonthDayValue.java</include>
958+
<include>src/main/java/org/exist/xquery/value/GMonthValue.java</include>
959+
<include>src/main/java/org/exist/xquery/value/GYearMonthValue.java</include>
960+
<include>src/main/java/org/exist/xquery/value/GYearValue.java</include>
961+
<include>src/main/java/org/exist/xquery/value/IntegerValue.java</include>
962+
<include>src/main/java/org/exist/xquery/value/QNameValue.java</include>
963+
<include>src/main/java/org/exist/xquery/value/StringValue.java</include>
964+
<include>src/main/java/org/exist/xquery/value/TimeValue.java</include>
965+
<include>src/main/java/org/exist/xquery/value/YearMonthDurationValue.java</include>
942966
<include>src/main/java/org/exist/xquery/value/SequenceType.java</include>
943967
<include>src/main/java/org/exist/xquery/value/TimeUtils.java</include>
944968
<include>src/main/java/org/exist/xquery/value/Type.java</include>
@@ -1017,6 +1041,7 @@
10171041
<exclude>src/main/java/org/exist/collections/triggers/XQueryStartupTrigger.java</exclude>
10181042
<exclude>src/main/java/org/exist/config/Configuration.java</exclude>
10191043
<exclude>src/main/java/org/exist/config/ConfigurationImpl.java</exclude>
1044+
<exclude>src/main/java/org/exist/dom/QName.java</exclude>
10201045
<exclude>src/main/java/org/exist/dom/memtree/AttrImpl.java</exclude>
10211046
<exclude>src/main/java/org/exist/dom/memtree/DocumentImpl.java</exclude>
10221047
<exclude>src/main/java/org/exist/dom/memtree/DocumentTypeImpl.java</exclude>
@@ -1134,6 +1159,8 @@
11341159
<exclude>src/main/java/org/exist/storage/io/AbstractVariableByteOutput.java</exclude>
11351160
<exclude>src/main/java/org/exist/storage/io/VariableByteArrayInput.java</exclude>
11361161
<exclude>src/main/java/org/exist/storage/io/VariableByteArrayOutputStream.java</exclude>
1162+
<exclude>src/main/java/org/exist/storage/io/VariableByteBufferInput.java</exclude>
1163+
<exclude>src/main/java/org/exist/storage/io/VariableByteBufferOutput.java</exclude>
11371164
<exclude>src/main/java/org/exist/storage/io/VariableByteFilterInputStream.java</exclude>
11381165
<exclude>src/main/java/org/exist/storage/io/VariableByteFilterOutputStream.java</exclude>
11391166
<exclude>src/main/java/org/exist/storage/io/VariableByteInput.java</exclude>
@@ -1278,19 +1305,40 @@
12781305
<exclude>src/main/java/org/exist/xquery/util/SerializerUtils.java</exclude>
12791306
<exclude>src/test/java/org/exist/xquery/util/URIUtilsTest.java</exclude>
12801307
<exclude>src/main/java/org/exist/xquery/value/AbstractDateTimeValue.java</exclude>
1308+
<exclude>src/main/java/org/exist/xquery/value/AnyURIValue.java</exclude>
12811309
<exclude>src/main/java/org/exist/xquery/value/ArrayListValueSequence.java</exclude>
12821310
<exclude>src/main/java/org/exist/xquery/value/AtomicValueComparator.java</exclude>
12831311
<exclude>src/test/java/org/exist/xquery/value/Base64BinaryValueTypeTest.java</exclude>
12841312
<exclude>src/test/java/org/exist/xquery/value/BifurcanMapTest.java</exclude>
1313+
<exclude>src/main/java/org/exist/xquery/value/BinaryValue.java</exclude>
1314+
<exclude>src/main/java/org/exist/xquery/value/BooleanValue.java</exclude>
1315+
<exclude>src/main/java/org/exist/xquery/value/DateTimeStampValue.java</exclude>
12851316
<exclude>src/test/java/org/exist/xquery/value/DateTimeTypesTest.java</exclude>
1317+
<exclude>src/main/java/org/exist/xquery/value/DateTimeValue.java</exclude>
1318+
<exclude>src/main/java/org/exist/xquery/value/DateValue.java</exclude>
1319+
<exclude>src/main/java/org/exist/xquery/value/DayTimeDurationValue.java</exclude>
1320+
<exclude>src/main/java/org/exist/xquery/value/DecimalValue.java</exclude>
1321+
<exclude>src/main/java/org/exist/xquery/value/DoubleValue.java</exclude>
1322+
<exclude>src/main/java/org/exist/xquery/value/DurationValue.java</exclude>
1323+
<exclude>src/main/java/org/exist/xquery/value/FloatValue.java</exclude>
1324+
<exclude>src/main/java/org/exist/xquery/value/GDayValue.java</exclude>
1325+
<exclude>src/main/java/org/exist/xquery/value/GMonthDayValue.java</exclude>
1326+
<exclude>src/main/java/org/exist/xquery/value/GMonthValue.java</exclude>
1327+
<exclude>src/main/java/org/exist/xquery/value/GYearMonthValue.java</exclude>
1328+
<exclude>src/main/java/org/exist/xquery/value/GYearValue.java</exclude>
1329+
<exclude>src/main/java/org/exist/xquery/value/IntegerValue.java</exclude>
12861330
<exclude>src/main/java/org/exist/xquery/value/ItemComparator.java</exclude>
1331+
<exclude>src/main/java/org/exist/xquery/value/QNameValue.java</exclude>
12871332
<exclude>src/main/java/org/exist/xquery/value/SequenceComparator.java</exclude>
12881333
<exclude>src/main/java/org/exist/xquery/value/SequenceType.java</exclude>
1334+
<exclude>src/main/java/org/exist/xquery/value/StringValue.java</exclude>
12891335
<exclude>src/main/java/org/exist/xquery/value/SubSequence.java</exclude>
12901336
<exclude>src/test/java/org/exist/xquery/value/SubSequenceRangeTest.java</exclude>
12911337
<exclude>src/test/java/org/exist/xquery/value/SubSequenceTest.java</exclude>
1338+
<exclude>src/main/java/org/exist/xquery/value/TimeValue.java</exclude>
12921339
<exclude>src/main/java/org/exist/xquery/value/TimeUtils.java</exclude>
12931340
<exclude>src/main/java/org/exist/xquery/value/Type.java</exclude>
1341+
<exclude>src/main/java/org/exist/xquery/value/YearMonthDurationValue.java</exclude>
12941342
<exclude>src/main/java/org/exist/xslt/EXistURIResolver.java</exclude>
12951343
<exclude>src/main/java/org/exist/xslt/XsltURIResolverHelper.java</exclude>
12961344

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+
* admin@evolvedbinary.com
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:wolfgang@exist-db.org">Wolfgang</a>
65+
* @author <a href="mailto:adam@evolvedbinary.com">Adam Retter</a>
3966
*/
4067
public class QName implements Comparable<QName> {
4168

@@ -136,7 +163,18 @@ public byte getNameType() {
136163
* @return the string representation of this qualified name.
137164
* */
138165
public String getStringValue() {
139-
return getStringRepresentation(false);
166+
return getStringRepresentation(false, false);
167+
}
168+
169+
/**
170+
* Get an extended string representation of this qualified name.
171+
*
172+
* Will be of the format `local-name`, `{namespace}local-name`, or `{namespace}prefix:local-name`.
173+
*
174+
* @return the string representation of this qualified name.
175+
*/
176+
public String getExtendedStringValue() {
177+
return getStringRepresentation(false, true);
140178
}
141179

142180
/**
@@ -148,23 +186,32 @@ public String getStringValue() {
148186
*/
149187
@Override
150188
public String toString() {
151-
return getStringRepresentation(true);
189+
return getStringRepresentation(true, false);
152190
}
153191

154192
/**
155193
* Get a string representation of this qualified name.
156194
*
157195
* @param showNsWithoutPrefix true if the namespace should be shown even when there is no prefix, false otherwise.
158-
* When shown, it will be output using Clark notation, e.g. `{http://namespace}local-name`.
196+
* When shown, it will be output using Clark notation, e.g. `{namespace}local-name`.
197+
*
198+
* @param extended true if the namespace and prefix should be shown, requires showNsWithoutPrefix == false.
159199
*
160200
* @return the string representation of this qualified name.
161201
*/
162-
private String getStringRepresentation(final boolean showNsWithoutPrefix) {
202+
private String getStringRepresentation(final boolean showNsWithoutPrefix, final boolean extended) {
163203
if (prefix != null && !prefix.isEmpty()) {
164-
return prefix + COLON + localPart;
165-
} else if (showNsWithoutPrefix && namespaceURI != null && !XMLConstants.NULL_NS_URI.equals(namespaceURI)) {
204+
if (extended) {
205+
return LEFT_BRACE + namespaceURI + RIGHT_BRACE + prefix + COLON + localPart;
206+
} else {
207+
return prefix + COLON + localPart;
208+
}
209+
}
210+
211+
if (showNsWithoutPrefix && namespaceURI != null && !XMLConstants.NULL_NS_URI.equals(namespaceURI)) {
166212
return LEFT_BRACE + namespaceURI + RIGHT_BRACE + localPart;
167213
}
214+
168215
return localPart;
169216
}
170217

@@ -343,6 +390,52 @@ public static QName parse(final String namespaceURI, final String qname) throws
343390
private final static Pattern ptnClarkNotation = Pattern.compile("\\{([^&{}]*)\\}([^&{}:]+)");
344391
private final static Pattern ptnEqNameNotation = Pattern.compile("Q" + ptnClarkNotation);
345392

393+
/**
394+
* Extract a QName from a namespace and qualified name string.
395+
*
396+
* @param extendedStringValue a string representation as produced by {@link #getExtendedStringValue()}, i.e.: `local-name`, `{namespace}local-name`, or `{namespace}prefix:local-name`.
397+
* @return The QName
398+
* @throws IllegalQNameException if the qname component is invalid
399+
*/
400+
public static QName parse(String extendedStringValue) throws IllegalQNameException {
401+
if (isNullOrEmpty(extendedStringValue)) {
402+
throw new IllegalQNameException(ILLEGAL_FORMAT.val, "Illegal extended string QName is empty");
403+
}
404+
405+
final String namespaceUri;
406+
if (extendedStringValue.charAt(0) == LEFT_BRACE) {
407+
final int idxNsEnd = extendedStringValue.indexOf(RIGHT_BRACE);
408+
if (idxNsEnd == Constants.STRING_NOT_FOUND) {
409+
throw new IllegalQNameException(ILLEGAL_FORMAT.val, "Illegal extended string QName, missing right brace: '" + extendedStringValue + "'");
410+
}
411+
namespaceUri = extendedStringValue.substring(1, idxNsEnd);
412+
extendedStringValue = extendedStringValue.substring(idxNsEnd + 1);
413+
} else if (extendedStringValue.indexOf(RIGHT_BRACE) != Constants.STRING_NOT_FOUND) {
414+
throw new IllegalQNameException(ILLEGAL_FORMAT.val, "Illegal extended string QName, missing left brace: '" + extendedStringValue + "'");
415+
} else {
416+
namespaceUri = XMLConstants.NULL_NS_URI;
417+
}
418+
419+
@Nullable final String prefix;
420+
final int idxColon = extendedStringValue.indexOf(COLON);
421+
if (idxColon == Constants.STRING_NOT_FOUND) {
422+
prefix = null;
423+
} else {
424+
prefix = extendedStringValue.substring(0, idxColon);
425+
if (!XMLNames.isNCName(prefix)) {
426+
throw new IllegalQNameException(INVALID_PREFIX.val, "Illegal extended string QName, invalid prefix: '" + extendedStringValue + "'");
427+
}
428+
extendedStringValue = extendedStringValue.substring(idxColon + 1);
429+
}
430+
431+
final String localPart = extendedStringValue;
432+
if (!XMLNames.isNCName(localPart)) {
433+
throw new IllegalQNameException(INVALID_LOCAL_PART.val, "Illegal extended string QName, invalid prefix: '" + extendedStringValue + "'");
434+
}
435+
436+
return new QName(localPart, namespaceUri, prefix);
437+
}
438+
346439
/**
347440
* Parses the given string into a QName. The method uses context to look up
348441
* 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;
@@ -1387,6 +1388,10 @@ public String getNamespaceForPrefix(final String prefix) {
13871388
return namespaceMappings.get(prefix);
13881389
}
13891390

1391+
public @Nullable Map<String, String> getNamespaceMappings() {
1392+
return namespaceMappings;
1393+
}
1394+
13901395
/**
13911396
* @see java.lang.Object#toString()
13921397
*/

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;
@@ -2366,6 +2369,48 @@ public long readFixedLong() throws IOException {
23662369
return r;
23672370
}
23682371

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

0 commit comments

Comments
 (0)