Skip to content

Commit c5ac185

Browse files
committed
feat(unknownType): add support for Bolt Unknown Type
1 parent 2d8ae2d commit c5ac185

File tree

15 files changed

+242
-5
lines changed

15 files changed

+242
-5
lines changed

driver/clirr-ignored-differences.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,5 +905,10 @@
905905
<differenceType>8001</differenceType>
906906
</difference>
907907

908+
<difference>
909+
<className>org/neo4j/driver/types/TypeSystem</className>
910+
<differenceType>7012</differenceType>
911+
<method>org.neo4j.driver.types.Type UNKNOWN()</method>
912+
</difference>
908913

909914
</differences>

driver/src/main/java/org/neo4j/driver/Value.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import org.neo4j.driver.types.Relationship;
4343
import org.neo4j.driver.types.Type;
4444
import org.neo4j.driver.types.TypeSystem;
45+
import org.neo4j.driver.types.UnknownTypeData;
4546
import org.neo4j.driver.util.Immutable;
4647
import org.neo4j.driver.util.Preview;
4748

@@ -679,6 +680,10 @@ public interface Value extends MapAccessor, MapAccessorWithDefaultValue {
679680
* <td>{@link TypeSystem#RELATIONSHIP}</td>
680681
* <td>{@link Relationship}</td>
681682
* </tr>
683+
* <tr>
684+
* <td>{@link TypeSystem#UNKNOWN}</td>
685+
* <td>{@link UnknownTypeData}</td>
686+
* </tr>
682687
* </tbody>
683688
* </table>
684689
*

driver/src/main/java/org/neo4j/driver/Values.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
import org.neo4j.driver.internal.value.PointValue;
6868
import org.neo4j.driver.internal.value.StringValue;
6969
import org.neo4j.driver.internal.value.TimeValue;
70+
import org.neo4j.driver.internal.value.UnknownValue;
7071
import org.neo4j.driver.internal.value.VectorValue;
7172
import org.neo4j.driver.mapping.Property;
7273
import org.neo4j.driver.types.Entity;
@@ -77,6 +78,7 @@
7778
import org.neo4j.driver.types.Point;
7879
import org.neo4j.driver.types.Relationship;
7980
import org.neo4j.driver.types.TypeSystem;
81+
import org.neo4j.driver.types.UnknownTypeData;
8082
import org.neo4j.driver.types.Vector;
8183
import org.neo4j.driver.util.Preview;
8284

@@ -182,6 +184,9 @@ public static Value value(Object value) {
182184
if (value instanceof Vector vector) {
183185
return value(vector);
184186
}
187+
if (value instanceof UnknownTypeData) {
188+
return value((UnknownTypeData) value);
189+
}
185190

186191
if (value instanceof List<?>) {
187192
return value((List<Object>) value);
@@ -1149,4 +1154,8 @@ private static Value vector(Object array) {
11491154
"Unsupported vector element type: " + array.getClass().getName());
11501155
}
11511156
}
1157+
1158+
private static Value value(UnknownTypeData unknownTypeData) {
1159+
return new UnknownValue(unknownTypeData);
1160+
}
11521161
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [https://neo4j.com]
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.neo4j.driver.internal;
18+
19+
import java.util.Optional;
20+
import org.neo4j.driver.types.UnknownTypeData;
21+
22+
public record InternalUnknownTypeData(String name, String minProtocolVersion, String messageValue)
23+
implements UnknownTypeData {
24+
@Override
25+
public Optional<String> message() {
26+
return Optional.ofNullable(messageValue);
27+
}
28+
}

driver/src/main/java/org/neo4j/driver/internal/types/InternalTypeSystem.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import static org.neo4j.driver.internal.types.TypeConstructor.RELATIONSHIP;
3737
import static org.neo4j.driver.internal.types.TypeConstructor.STRING;
3838
import static org.neo4j.driver.internal.types.TypeConstructor.TIME;
39+
import static org.neo4j.driver.internal.types.TypeConstructor.UNKNOWN;
3940
import static org.neo4j.driver.internal.types.TypeConstructor.VECTOR;
4041

4142
import org.neo4j.driver.Value;
@@ -72,6 +73,7 @@ public class InternalTypeSystem implements TypeSystem {
7273
private final TypeRepresentation durationType = constructType(DURATION);
7374
private final TypeRepresentation nullType = constructType(NULL);
7475
private final TypeRepresentation vectorType = constructType(VECTOR);
76+
private final TypeRepresentation unknownType = constructType(UNKNOWN);
7577

7678
private InternalTypeSystem() {}
7779

@@ -180,6 +182,11 @@ public Type VECTOR() {
180182
return vectorType;
181183
}
182184

185+
@Override
186+
public Type UNKNOWN() {
187+
return unknownType;
188+
}
189+
183190
private TypeRepresentation constructType(TypeConstructor tyCon) {
184191
return new TypeRepresentation(tyCon);
185192
}

driver/src/main/java/org/neo4j/driver/internal/types/TypeConstructor.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ public boolean covers(Value value) {
5757
DATE_TIME,
5858
DURATION,
5959
NULL,
60-
VECTOR;
60+
VECTOR,
61+
UNKNOWN;
6162

6263
private static TypeConstructor typeConstructorOf(Value value) {
6364
return ((InternalValue) value).typeConstructor();

driver/src/main/java/org/neo4j/driver/internal/value/BoltValueFactory.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,19 @@
2929
import java.util.Collections;
3030
import java.util.List;
3131
import java.util.Map;
32+
import org.neo4j.bolt.connection.BoltProtocolVersion;
3233
import org.neo4j.bolt.connection.values.Node;
3334
import org.neo4j.bolt.connection.values.Path;
3435
import org.neo4j.bolt.connection.values.Relationship;
3536
import org.neo4j.bolt.connection.values.Segment;
37+
import org.neo4j.bolt.connection.values.Type;
3638
import org.neo4j.bolt.connection.values.Value;
3739
import org.neo4j.bolt.connection.values.ValueFactory;
3840
import org.neo4j.driver.Values;
3941
import org.neo4j.driver.internal.InternalNode;
4042
import org.neo4j.driver.internal.InternalPath;
4143
import org.neo4j.driver.internal.InternalRelationship;
44+
import org.neo4j.driver.internal.InternalUnknownTypeData;
4245

4346
public class BoltValueFactory implements ValueFactory {
4447
private static final BoltValueFactory INSTANCE = new BoltValueFactory();
@@ -265,6 +268,14 @@ public Value vector(Class<?> elementType, Object elements) {
265268
return value;
266269
}
267270

271+
@Override
272+
public Value unknown(String name, BoltProtocolVersion minBoltVersion, Map<String, Value> extra) {
273+
var message = extra.get("message");
274+
var messageString = message.boltValueType().equals(Type.STRING) ? message.asString() : null;
275+
return (InternalValue)
276+
Values.value((Object) new InternalUnknownTypeData(name, minBoltVersion.toString(), messageString));
277+
}
278+
268279
@Override
269280
public Value unsupportedDateTimeValue(DateTimeException e) {
270281
return new UnsupportedDateTimeValue(e);
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [https://neo4j.com]
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.neo4j.driver.internal.value;
18+
19+
import org.neo4j.driver.internal.types.InternalTypeSystem;
20+
import org.neo4j.driver.types.UnknownTypeData;
21+
22+
public final class UnknownValue extends ObjectValueAdapter<UnknownTypeData> {
23+
public UnknownValue(UnknownTypeData adapted) {
24+
super(adapted);
25+
}
26+
27+
@Override
28+
public org.neo4j.bolt.connection.values.Type boltValueType() {
29+
return org.neo4j.bolt.connection.values.Type.UNKNOWN;
30+
}
31+
32+
@Override
33+
public org.neo4j.driver.types.Type type() {
34+
return InternalTypeSystem.TYPE_SYSTEM.UNKNOWN();
35+
}
36+
37+
@Override
38+
public <T> T as(Class<T> targetClass) {
39+
if (targetClass.isAssignableFrom(UnknownTypeData.class)) {
40+
return targetClass.cast(asObject());
41+
}
42+
return asMapped(targetClass);
43+
}
44+
}

driver/src/main/java/org/neo4j/driver/types/TypeSystem.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,4 +164,20 @@ static TypeSystem getDefault() {
164164
*/
165165
@Preview(name = "Neo4j Vector")
166166
Type VECTOR();
167+
168+
/**
169+
* Returns a {@link Type} instance representing an unknown type.
170+
* <p>
171+
* An unknown type may occur when a new type is introduced in the Neo4j server and the driver is connected over an
172+
* older Bolt Protocol version that does not support this type. The {@link UnknownTypeData} object provides information
173+
* about the unknown type and the {@link UnknownTypeData#minProtocolVersion()} needed to transmit it. However, the
174+
* {@link UnknownTypeData} object itself requires at least Bolt Protocol 6.0.
175+
* <p>
176+
* Note that the unknown type MUST NOT be sent to the server.
177+
*
178+
* @return the type instance
179+
* @since 6.0.0
180+
* @see UnknownTypeData
181+
*/
182+
Type UNKNOWN();
167183
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [https://neo4j.com]
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.neo4j.driver.types;
18+
19+
import java.util.Optional;
20+
21+
/**
22+
* An object instance of {@link TypeSystem#UNKNOWN()} type.
23+
* <p>
24+
* This object contains information about the unknown type and the {@link #minProtocolVersion()} needed to transmit it.
25+
* <p>
26+
* Note that this object MUST NOT be sent to the server.
27+
*
28+
* @since 6.0.0
29+
*/
30+
public interface UnknownTypeData {
31+
/**
32+
* Returns the type name.
33+
* @return the type name
34+
*/
35+
String name();
36+
37+
/**
38+
* The minimum Bolt Protocol version needed to transmit this type.
39+
* @return the minimum Bolt Protocol version
40+
*/
41+
String minProtocolVersion();
42+
43+
/**
44+
* An optional message.
45+
* @return the message
46+
*/
47+
Optional<String> message();
48+
}

0 commit comments

Comments
 (0)