Skip to content

Commit 002edfb

Browse files
committed
GH-4950 LMDB: fix handling of doubles and code cleanup
1 parent f4b189d commit 002edfb

5 files changed

Lines changed: 81 additions & 120 deletions

File tree

core/sail/lmdb/src/main/java/org/eclipse/rdf4j/sail/lmdb/TripleStore.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,9 @@ protected void filterUsedIds(Collection<Long> ids) throws IOException {
630630
if (component != 2) {
631631
// optimization: ensure that literals are only tested if they appear in object
632632
// position
633-
if (ValueIds.getIdType(id) == ValueIds.T_LITERAL) {
633+
switch (ValueIds.getIdType(id)) {
634+
case ValueIds.T_DOUBLE:
635+
case ValueIds.T_LITERAL:
634636
// id is a literal, don't test it
635637
continue;
636638
}

core/sail/lmdb/src/main/java/org/eclipse/rdf4j/sail/lmdb/ValueIds.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@
1414
* Constants and functions for working with ids encoded into long values.
1515
*/
1616
public class ValueIds {
17+
/**
18+
* An inlined double value. The least significant bit of the value is set to 1 to distinguish it from other inlined
19+
* values and references.
20+
*/
21+
public static final int T_DOUBLE = -1;
22+
1723
/**
1824
* Pointer to an arbitrary value in the value store. This is not used as RDF value.
1925
*/
@@ -78,7 +84,7 @@ public static long getValue(long id) {
7884
* @return A composite id.
7985
*/
8086
public static long createId(int idType, long value) {
81-
return value << 7 | idType << 1;
87+
return value << 7 | (long) idType << 1;
8288
}
8389

8490
/**
@@ -88,6 +94,17 @@ public static long createId(int idType, long value) {
8894
* @return <code>true</code> if the value is inlined, else <code>false</code>
8995
*/
9096
public static boolean isInlined(long id) {
91-
return getIdType(id) >= T_INTEGER;
97+
return isDouble(id) || getIdType(id) >= T_INTEGER;
98+
}
99+
100+
/**
101+
* Tests if the given id is an inlined double value, which is identified by the least significant bit being set to
102+
* 1.
103+
*
104+
* @param value The id's value
105+
* @return <code>true</code> if the value is an inlined double, else <code>false</code>
106+
*/
107+
public static boolean isDouble(long value) {
108+
return (value & 1L) != 0;
92109
}
93110
}

core/sail/lmdb/src/main/java/org/eclipse/rdf4j/sail/lmdb/ValueStore.java

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -405,24 +405,13 @@ private void open() throws IOException {
405405
}
406406

407407
private long nextId(byte valueType) throws IOException {
408-
int idType;
409-
switch (valueType) {
410-
case URI_VALUE:
411-
idType = ValueIds.T_URI;
412-
break;
413-
case BNODE_VALUE:
414-
idType = ValueIds.T_BNODE;
415-
break;
416-
case LITERAL_VALUE:
417-
idType = ValueIds.T_LITERAL;
418-
break;
419-
case NAMESPACE_VALUE:
420-
idType = ValueIds.T_PTR;
421-
break;
422-
default:
423-
throw new IllegalArgumentException("Unexpected value type: " + valueType);
424-
425-
}
408+
int idType = switch (valueType) {
409+
case URI_VALUE -> ValueIds.T_URI;
410+
case BNODE_VALUE -> ValueIds.T_BNODE;
411+
case LITERAL_VALUE -> ValueIds.T_LITERAL;
412+
case NAMESPACE_VALUE -> ValueIds.T_PTR;
413+
default -> throw new IllegalArgumentException("Unexpected value type: " + valueType);
414+
};
426415
if (freeIdsAvailable) {
427416
// next id from store
428417
Long reusedId = writeTransaction((stack, txn) -> {
@@ -569,6 +558,7 @@ public LmdbValue getLazyValue(long id) throws IOException {
569558
case ValueIds.T_URI:
570559
resultValue = new LmdbIRI(lazyRevision, id);
571560
break;
561+
case ValueIds.T_DOUBLE:
572562
case ValueIds.T_LITERAL:
573563
resultValue = new LmdbLiteral(lazyRevision, id);
574564
break;
@@ -580,7 +570,7 @@ public LmdbValue getLazyValue(long id) throws IOException {
580570
resultValue = new LmdbLiteral(lazyRevision, id);
581571
break;
582572
}
583-
throw new IOException("Unsupported value with id type: " + idType);
573+
throw new IOException("Unsupported value with id=" + id + " and id type " + idType);
584574
}
585575
}
586576

core/sail/lmdb/src/main/java/org/eclipse/rdf4j/sail/lmdb/inlined/Decimals.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,7 @@ static long packDouble(double value) {
106106
// encoding of exponent was possible
107107
int sign = value < 0 ? 1 : 0;
108108
long mantissa = valueBits & 0x000fffffffffffffL;
109-
long encoded = ((long) exponent10) << 54 | mantissa << 2 | sign << 1 | 1;
110-
return encoded;
109+
return ((long) exponent10) << 54 | mantissa << 2 | sign << 1 | 1;
111110
}
112111
return 0L;
113112
}

core/sail/lmdb/src/main/java/org/eclipse/rdf4j/sail/lmdb/inlined/Values.java

Lines changed: 49 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -35,106 +35,59 @@ public static long packLiteral(Literal literal) {
3535
if (xsdDataType == null) {
3636
return 0L;
3737
}
38-
switch (xsdDataType) {
39-
case DECIMAL:
40-
return packDecimal(literal.decimalValue());
41-
case DOUBLE:
42-
return packDouble(literal.doubleValue());
43-
case FLOAT:
44-
return packFloat(literal.floatValue());
45-
case INTEGER:
46-
return packInteger(literal);
47-
case LONG:
48-
return packLong(literal);
49-
case INT:
50-
return packInt(literal);
51-
case SHORT:
52-
return packShort(literal);
53-
case BYTE:
54-
return packByte(literal);
55-
case UNSIGNED_LONG:
56-
return packUnsignedLong(literal);
57-
case UNSIGNED_INT:
58-
return packUnsignedInt(literal);
59-
case UNSIGNED_SHORT:
60-
return packUnsignedShort(literal);
61-
case UNSIGNED_BYTE:
62-
return packUnsignedByte(literal);
63-
case POSITIVE_INTEGER:
64-
return packPositiveInteger(literal);
65-
case NEGATIVE_INTEGER:
66-
return packNegativeInteger(literal);
67-
case NON_NEGATIVE_INTEGER:
68-
return packNonNegativeInteger(literal);
69-
case NON_POSITIVE_INTEGER:
70-
return packNonPositiveInteger(literal);
71-
case STRING:
72-
return packString(literal);
73-
case DATETIME:
74-
return packDateTime(literal);
75-
case DATETIMESTAMP:
76-
return packDateTimeStamp(literal);
77-
case DATE:
78-
return packDate(literal);
79-
case BOOLEAN:
80-
return packBoolean(literal);
81-
default:
38+
return switch (xsdDataType) {
39+
case DECIMAL -> packDecimal(literal.decimalValue());
40+
case DOUBLE -> packDouble(literal.doubleValue());
41+
case FLOAT -> packFloat(literal.floatValue());
42+
case INTEGER -> packInteger(literal);
43+
case LONG -> packLong(literal);
44+
case INT -> packInt(literal);
45+
case SHORT -> packShort(literal);
46+
case BYTE -> packByte(literal);
47+
case UNSIGNED_LONG -> packUnsignedLong(literal);
48+
case UNSIGNED_INT -> packUnsignedInt(literal);
49+
case UNSIGNED_SHORT -> packUnsignedShort(literal);
50+
case UNSIGNED_BYTE -> packUnsignedByte(literal);
51+
case POSITIVE_INTEGER -> packPositiveInteger(literal);
52+
case NEGATIVE_INTEGER -> packNegativeInteger(literal);
53+
case NON_NEGATIVE_INTEGER -> packNonNegativeInteger(literal);
54+
case NON_POSITIVE_INTEGER -> packNonPositiveInteger(literal);
55+
case STRING -> packString(literal);
56+
case DATETIME -> packDateTime(literal);
57+
case DATETIMESTAMP -> packDateTimeStamp(literal);
58+
case DATE -> packDate(literal);
59+
case BOOLEAN -> packBoolean(literal);
60+
default ->
8261
// unsupported type
83-
return 0L;
84-
}
62+
0L;
63+
};
8564
}
8665

8766
public static Literal unpackLiteral(long value, ValueFactory valueFactory) {
88-
// special handling for double values
89-
if (isDouble(value)) {
90-
return unpackDouble(value, valueFactory);
91-
}
92-
9367
int idType = ValueIds.getIdType(value);
94-
95-
switch (idType) {
96-
case ValueIds.T_DECIMAL:
97-
return unpackDecimal(value, valueFactory);
98-
case ValueIds.T_FLOAT:
99-
return unpackFloat(value, valueFactory);
100-
case ValueIds.T_INTEGER:
101-
return unpackInteger(value, valueFactory);
102-
case ValueIds.T_LONG:
103-
return unpackLong(value, valueFactory);
104-
case ValueIds.T_INT:
105-
return unpackInt(value, valueFactory);
106-
case ValueIds.T_SHORT:
107-
return unpackShort(value, valueFactory);
108-
case ValueIds.T_BYTE:
109-
return unpackByte(value, valueFactory);
110-
case ValueIds.T_UNSIGNEDLONG:
111-
return unpackUnsignedLong(value, valueFactory);
112-
case ValueIds.T_UNSIGNEDINT:
113-
return unpackUnsignedInt(value, valueFactory);
114-
case ValueIds.T_UNSIGNEDSHORT:
115-
return unpackUnsignedShort(value, valueFactory);
116-
case ValueIds.T_UNSIGNEDBYTE:
117-
return unpackUnsignedByte(value, valueFactory);
118-
case ValueIds.T_POSITIVE_INTEGER:
119-
return unpackPositiveInteger(value, valueFactory);
120-
case ValueIds.T_NEGATIVE_INTEGER:
121-
return unpackNegativeInteger(value, valueFactory);
122-
case ValueIds.T_NON_NEGATIVE_INTEGER:
123-
return unpackNonNegativeInteger(value, valueFactory);
124-
case ValueIds.T_NON_POSITIVE_INTEGER:
125-
return unpackNonPositiveInteger(value, valueFactory);
126-
case ValueIds.T_SHORTSTRING:
127-
return unpackString(value, valueFactory);
128-
case ValueIds.T_DATETIME:
129-
return unpackDateTime(value, valueFactory);
130-
case ValueIds.T_DATETIMESTAMP:
131-
return unpackDateTimeStamp(value, valueFactory);
132-
case ValueIds.T_DATE:
133-
return unpackDate(value, valueFactory);
134-
case ValueIds.T_BOOLEAN:
135-
return unpackBoolean(value, valueFactory);
136-
default:
137-
throw new IllegalArgumentException("Invalid packed value with id type: " + idType);
138-
}
68+
return switch (idType) {
69+
case ValueIds.T_DOUBLE -> unpackDouble(value, valueFactory);
70+
case ValueIds.T_DECIMAL -> unpackDecimal(value, valueFactory);
71+
case ValueIds.T_FLOAT -> unpackFloat(value, valueFactory);
72+
case ValueIds.T_INTEGER -> unpackInteger(value, valueFactory);
73+
case ValueIds.T_LONG -> unpackLong(value, valueFactory);
74+
case ValueIds.T_INT -> unpackInt(value, valueFactory);
75+
case ValueIds.T_SHORT -> unpackShort(value, valueFactory);
76+
case ValueIds.T_BYTE -> unpackByte(value, valueFactory);
77+
case ValueIds.T_UNSIGNEDLONG -> unpackUnsignedLong(value, valueFactory);
78+
case ValueIds.T_UNSIGNEDINT -> unpackUnsignedInt(value, valueFactory);
79+
case ValueIds.T_UNSIGNEDSHORT -> unpackUnsignedShort(value, valueFactory);
80+
case ValueIds.T_UNSIGNEDBYTE -> unpackUnsignedByte(value, valueFactory);
81+
case ValueIds.T_POSITIVE_INTEGER -> unpackPositiveInteger(value, valueFactory);
82+
case ValueIds.T_NEGATIVE_INTEGER -> unpackNegativeInteger(value, valueFactory);
83+
case ValueIds.T_NON_NEGATIVE_INTEGER -> unpackNonNegativeInteger(value, valueFactory);
84+
case ValueIds.T_NON_POSITIVE_INTEGER -> unpackNonPositiveInteger(value, valueFactory);
85+
case ValueIds.T_SHORTSTRING -> unpackString(value, valueFactory);
86+
case ValueIds.T_DATETIME -> unpackDateTime(value, valueFactory);
87+
case ValueIds.T_DATETIMESTAMP -> unpackDateTimeStamp(value, valueFactory);
88+
case ValueIds.T_DATE -> unpackDate(value, valueFactory);
89+
case ValueIds.T_BOOLEAN -> unpackBoolean(value, valueFactory);
90+
default -> throw new IllegalArgumentException("Invalid packed value with id type: " + idType);
91+
};
13992
}
14093
}

0 commit comments

Comments
 (0)