Skip to content

Commit b8b77f6

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 dd406d7 commit b8b77f6

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
@@ -741,6 +741,8 @@
741741
<include>src/main/java/org/exist/dom/memtree/reference/TextReferenceImpl.java</include>
742742
<include>src/main/java/org/exist/storage/io/AbstractVariableByteOutput.java</include>
743743
<include>src/main/java/org/exist/storage/io/VariableByteArrayOutputStream.java</include>
744+
<include>src/main/java/org/exist/storage/io/VariableByteBufferInput.java</include>
745+
<include>src/main/java/org/exist/storage/io/VariableByteBufferOutput.java</include>
744746
<include>src/main/java/org/exist/storage/io/VariableByteFilterInputStream.java</include>
745747
<include>src/main/java/org/exist/storage/io/VariableByteFilterOutputStream.java</include>
746748
<include>src/main/java/org/exist/storage/io/VariableByteOutput.java</include>
@@ -829,6 +831,7 @@
829831
<include>src/main/java/org/exist/collections/triggers/XQueryStartupTrigger.java</include>
830832
<include>src/main/java/org/exist/config/Configuration.java</include>
831833
<include>src/main/java/org/exist/config/ConfigurationImpl.java</include>
834+
<include>src/main/java/org/exist/dom/QName.java</include>
832835
<include>src/main/java/org/exist/dom/memtree/AttrImpl.java</include>
833836
<include>src/main/java/org/exist/dom/memtree/DocumentImpl.java</include>
834837
<include>src/main/java/org/exist/dom/memtree/DOMIndexer.java</include>
@@ -993,7 +996,28 @@
993996
<include>src/test/java/org/exist/xquery/update/UpdateReplaceTest.java</include>
994997
<include>src/main/java/org/exist/xquery/util/SerializerUtils.java</include>
995998
<include>src/main/java/org/exist/xquery/value/AbstractDateTimeValue.java</include>
999+
<include>src/main/java/org/exist/xquery/value/AnyURIValue.java</include>
9961000
<include>src/test/java/org/exist/xquery/value/Base64BinaryValueTypeTest.java</include>
1001+
<include>src/main/java/org/exist/xquery/value/BinaryValue.java</include>
1002+
<include>src/main/java/org/exist/xquery/value/BooleanValue.java</include>
1003+
<include>src/main/java/org/exist/xquery/value/DateTimeStampValue.java</include>
1004+
<include>src/main/java/org/exist/xquery/value/DateTimeValue.java</include>
1005+
<include>src/main/java/org/exist/xquery/value/DateValue.java</include>
1006+
<include>src/main/java/org/exist/xquery/value/DayTimeDurationValue.java</include>
1007+
<include>src/main/java/org/exist/xquery/value/DecimalValue.java</include>
1008+
<include>src/main/java/org/exist/xquery/value/DoubleValue.java</include>
1009+
<include>src/main/java/org/exist/xquery/value/DurationValue.java</include>
1010+
<include>src/main/java/org/exist/xquery/value/FloatValue.java</include>
1011+
<include>src/main/java/org/exist/xquery/value/GDayValue.java</include>
1012+
<include>src/main/java/org/exist/xquery/value/GMonthDayValue.java</include>
1013+
<include>src/main/java/org/exist/xquery/value/GMonthValue.java</include>
1014+
<include>src/main/java/org/exist/xquery/value/GYearMonthValue.java</include>
1015+
<include>src/main/java/org/exist/xquery/value/GYearValue.java</include>
1016+
<include>src/main/java/org/exist/xquery/value/IntegerValue.java</include>
1017+
<include>src/main/java/org/exist/xquery/value/QNameValue.java</include>
1018+
<include>src/main/java/org/exist/xquery/value/StringValue.java</include>
1019+
<include>src/main/java/org/exist/xquery/value/TimeValue.java</include>
1020+
<include>src/main/java/org/exist/xquery/value/YearMonthDurationValue.java</include>
9971021
<include>src/main/java/org/exist/xquery/value/SequenceType.java</include>
9981022
<include>src/main/java/org/exist/xquery/value/TimeUtils.java</include>
9991023
<include>src/main/java/org/exist/xquery/value/Type.java</include>
@@ -1084,6 +1108,7 @@
10841108
<exclude>src/main/java/org/exist/collections/triggers/XQueryStartupTrigger.java</exclude>
10851109
<exclude>src/main/java/org/exist/config/Configuration.java</exclude>
10861110
<exclude>src/main/java/org/exist/config/ConfigurationImpl.java</exclude>
1111+
<exclude>src/main/java/org/exist/dom/QName.java</exclude>
10871112
<exclude>src/main/java/org/exist/dom/memtree/AttrImpl.java</exclude>
10881113
<exclude>src/main/java/org/exist/dom/memtree/DocumentImpl.java</exclude>
10891114
<exclude>src/main/java/org/exist/dom/memtree/DocumentTypeImpl.java</exclude>
@@ -1203,6 +1228,8 @@
12031228
<exclude>src/main/java/org/exist/storage/io/AbstractVariableByteOutput.java</exclude>
12041229
<exclude>src/main/java/org/exist/storage/io/VariableByteArrayInput.java</exclude>
12051230
<exclude>src/main/java/org/exist/storage/io/VariableByteArrayOutputStream.java</exclude>
1231+
<exclude>src/main/java/org/exist/storage/io/VariableByteBufferInput.java</exclude>
1232+
<exclude>src/main/java/org/exist/storage/io/VariableByteBufferOutput.java</exclude>
12061233
<exclude>src/main/java/org/exist/storage/io/VariableByteFilterInputStream.java</exclude>
12071234
<exclude>src/main/java/org/exist/storage/io/VariableByteFilterOutputStream.java</exclude>
12081235
<exclude>src/main/java/org/exist/storage/io/VariableByteInput.java</exclude>
@@ -1353,19 +1380,40 @@
13531380
<exclude>src/main/java/org/exist/xquery/util/SerializerUtils.java</exclude>
13541381
<exclude>src/test/java/org/exist/xquery/util/URIUtilsTest.java</exclude>
13551382
<exclude>src/main/java/org/exist/xquery/value/AbstractDateTimeValue.java</exclude>
1383+
<exclude>src/main/java/org/exist/xquery/value/AnyURIValue.java</exclude>
13561384
<exclude>src/main/java/org/exist/xquery/value/ArrayListValueSequence.java</exclude>
13571385
<exclude>src/main/java/org/exist/xquery/value/AtomicValueComparator.java</exclude>
13581386
<exclude>src/test/java/org/exist/xquery/value/Base64BinaryValueTypeTest.java</exclude>
13591387
<exclude>src/test/java/org/exist/xquery/value/BifurcanMapTest.java</exclude>
1388+
<exclude>src/main/java/org/exist/xquery/value/BinaryValue.java</exclude>
1389+
<exclude>src/main/java/org/exist/xquery/value/BooleanValue.java</exclude>
1390+
<exclude>src/main/java/org/exist/xquery/value/DateTimeStampValue.java</exclude>
13601391
<exclude>src/test/java/org/exist/xquery/value/DateTimeTypesTest.java</exclude>
1392+
<exclude>src/main/java/org/exist/xquery/value/DateTimeValue.java</exclude>
1393+
<exclude>src/main/java/org/exist/xquery/value/DateValue.java</exclude>
1394+
<exclude>src/main/java/org/exist/xquery/value/DayTimeDurationValue.java</exclude>
1395+
<exclude>src/main/java/org/exist/xquery/value/DecimalValue.java</exclude>
1396+
<exclude>src/main/java/org/exist/xquery/value/DoubleValue.java</exclude>
1397+
<exclude>src/main/java/org/exist/xquery/value/DurationValue.java</exclude>
1398+
<exclude>src/main/java/org/exist/xquery/value/FloatValue.java</exclude>
1399+
<exclude>src/main/java/org/exist/xquery/value/GDayValue.java</exclude>
1400+
<exclude>src/main/java/org/exist/xquery/value/GMonthDayValue.java</exclude>
1401+
<exclude>src/main/java/org/exist/xquery/value/GMonthValue.java</exclude>
1402+
<exclude>src/main/java/org/exist/xquery/value/GYearMonthValue.java</exclude>
1403+
<exclude>src/main/java/org/exist/xquery/value/GYearValue.java</exclude>
1404+
<exclude>src/main/java/org/exist/xquery/value/IntegerValue.java</exclude>
13611405
<exclude>src/main/java/org/exist/xquery/value/ItemComparator.java</exclude>
1406+
<exclude>src/main/java/org/exist/xquery/value/QNameValue.java</exclude>
13621407
<exclude>src/main/java/org/exist/xquery/value/SequenceComparator.java</exclude>
13631408
<exclude>src/main/java/org/exist/xquery/value/SequenceType.java</exclude>
1409+
<exclude>src/main/java/org/exist/xquery/value/StringValue.java</exclude>
13641410
<exclude>src/main/java/org/exist/xquery/value/SubSequence.java</exclude>
13651411
<exclude>src/test/java/org/exist/xquery/value/SubSequenceRangeTest.java</exclude>
13661412
<exclude>src/test/java/org/exist/xquery/value/SubSequenceTest.java</exclude>
1413+
<exclude>src/main/java/org/exist/xquery/value/TimeValue.java</exclude>
13671414
<exclude>src/main/java/org/exist/xquery/value/TimeUtils.java</exclude>
13681415
<exclude>src/main/java/org/exist/xquery/value/Type.java</exclude>
1416+
<exclude>src/main/java/org/exist/xquery/value/YearMonthDurationValue.java</exclude>
13691417
<exclude>src/main/java/org/exist/xslt/EXistURIResolver.java</exclude>
13701418
<exclude>src/main/java/org/exist/xslt/XsltURIResolverHelper.java</exclude>
13711419

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)