Skip to content

Commit df8b781

Browse files
authored
Add support for Bolt 5 (#1181)
* Add support for Bolt 5 * Update based on review comments
1 parent e9e8a93 commit df8b781

37 files changed

+1513
-121
lines changed

driver/clirr-ignored-differences.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,22 @@
8686
<to>org.neo4j.driver.Config$TrustStrategy trustCustomCertificateSignedBy(java.io.File[])</to>
8787
</difference>
8888

89+
<difference>
90+
<className>org/neo4j/driver/types/Entity</className>
91+
<differenceType>7012</differenceType>
92+
<method>java.lang.String elementId()</method>
93+
</difference>
94+
95+
<difference>
96+
<className>org/neo4j/driver/types/Relationship</className>
97+
<differenceType>7012</differenceType>
98+
<method>java.lang.String endNodeElementId()</method>
99+
</difference>
100+
101+
<difference>
102+
<className>org/neo4j/driver/types/Relationship</className>
103+
<differenceType>7012</differenceType>
104+
<method>java.lang.String startNodeElementId()</method>
105+
</difference>
106+
89107
</differences>

driver/src/main/java/org/neo4j/driver/internal/InternalEntity.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,27 @@
1919
package org.neo4j.driver.internal;
2020

2121
import java.util.Map;
22+
import java.util.function.Function;
2223

24+
import org.neo4j.driver.Value;
25+
import org.neo4j.driver.Values;
2326
import org.neo4j.driver.internal.util.Extract;
2427
import org.neo4j.driver.internal.util.Iterables;
2528
import org.neo4j.driver.internal.value.MapValue;
26-
import org.neo4j.driver.Value;
27-
import org.neo4j.driver.Values;
2829
import org.neo4j.driver.types.Entity;
29-
import java.util.function.Function;
3030

3131
import static org.neo4j.driver.Values.ofObject;
3232

3333
public abstract class InternalEntity implements Entity, AsValue
3434
{
3535
private final long id;
36+
private final String elementId;
3637
private final Map<String,Value> properties;
3738

38-
public InternalEntity( long id, Map<String, Value> properties )
39+
public InternalEntity( long id, String elementId, Map<String,Value> properties )
3940
{
4041
this.id = id;
42+
this.elementId = elementId;
4143
this.properties = properties;
4244
}
4345

@@ -47,6 +49,12 @@ public long id()
4749
return id;
4850
}
4951

52+
@Override
53+
public String elementId()
54+
{
55+
return elementId;
56+
}
57+
5058
@Override
5159
public int size()
5260
{

driver/src/main/java/org/neo4j/driver/internal/InternalNode.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222
import java.util.Collections;
2323
import java.util.Map;
2424

25+
import org.neo4j.driver.Value;
2526
import org.neo4j.driver.internal.value.NodeValue;
2627
import org.neo4j.driver.types.Node;
27-
import org.neo4j.driver.Value;
2828

2929
/**
3030
* {@link Node} implementation that directly contains labels and properties.
@@ -35,12 +35,12 @@ public class InternalNode extends InternalEntity implements Node
3535

3636
public InternalNode( long id )
3737
{
38-
this( id, Collections.<String>emptyList(), Collections.<String,Value>emptyMap() );
38+
this( id, String.valueOf( id ), Collections.emptyList(), Collections.emptyMap() );
3939
}
4040

41-
public InternalNode( long id, Collection<String> labels, Map<String, Value> properties )
41+
public InternalNode( long id, String elementId, Collection<String> labels, Map<String,Value> properties )
4242
{
43-
super( id, properties );
43+
super( id, elementId, properties );
4444
this.labels = labels;
4545
}
4646

driver/src/main/java/org/neo4j/driver/internal/InternalRelationship.java

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,30 +21,34 @@
2121
import java.util.Collections;
2222
import java.util.Map;
2323

24+
import org.neo4j.driver.Value;
2425
import org.neo4j.driver.internal.value.RelationshipValue;
2526
import org.neo4j.driver.types.Relationship;
26-
import org.neo4j.driver.Value;
2727

2828
/**
2929
* {@link Relationship} implementation that directly contains type and properties.
3030
*/
3131
public class InternalRelationship extends InternalEntity implements Relationship
3232
{
3333
private long start;
34+
private String startElementId;
3435
private long end;
36+
private String endElementId;
3537
private final String type;
3638

37-
public InternalRelationship( long id, long start, long end, String type )
39+
public InternalRelationship( long id, String elementId, long start, String startElementId, long end, String endElementId, String type )
3840
{
39-
this( id, start, end, type, Collections.<String,Value>emptyMap() );
41+
this( id, elementId, start, startElementId, end, endElementId, type, Collections.emptyMap() );
4042
}
4143

42-
public InternalRelationship( long id, long start, long end, String type,
43-
Map<String, Value> properties )
44+
public InternalRelationship( long id, String elementId, long start, String startElementId, long end, String endElementId, String type,
45+
Map<String,Value> properties )
4446
{
45-
super( id, properties );
47+
super( id, elementId, properties );
4648
this.start = start;
49+
this.startElementId = startElementId;
4750
this.end = end;
51+
this.endElementId = endElementId;
4852
this.type = type;
4953
}
5054

@@ -54,11 +58,15 @@ public boolean hasType( String relationshipType )
5458
return type().equals( relationshipType );
5559
}
5660

57-
/** Modify the start/end identities of this relationship */
58-
public void setStartAndEnd( long start, long end )
61+
/**
62+
* Modify the start/end identities of this relationship
63+
*/
64+
public void setStartAndEnd( long start, String startElementId, long end, String endElementId )
5965
{
6066
this.start = start;
67+
this.startElementId = startElementId;
6168
this.end = end;
69+
this.endElementId = endElementId;
6270
}
6371

6472
@Override
@@ -67,12 +75,24 @@ public long startNodeId()
6775
return start;
6876
}
6977

78+
@Override
79+
public String startNodeElementId()
80+
{
81+
return startElementId;
82+
}
83+
7084
@Override
7185
public long endNodeId()
7286
{
7387
return end;
7488
}
7589

90+
@Override
91+
public String endNodeElementId()
92+
{
93+
return endElementId;
94+
}
95+
7696
@Override
7797
public String type()
7898
{

driver/src/main/java/org/neo4j/driver/internal/async/connection/BoltProtocolUtil.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@
2222

2323
import org.neo4j.driver.internal.messaging.BoltProtocolVersion;
2424
import org.neo4j.driver.internal.messaging.v3.BoltProtocolV3;
25-
import org.neo4j.driver.internal.messaging.v4.BoltProtocolV4;
2625
import org.neo4j.driver.internal.messaging.v41.BoltProtocolV41;
2726
import org.neo4j.driver.internal.messaging.v42.BoltProtocolV42;
2827
import org.neo4j.driver.internal.messaging.v44.BoltProtocolV44;
28+
import org.neo4j.driver.internal.messaging.v5.BoltProtocolV5;
2929

3030
import static io.netty.buffer.Unpooled.copyInt;
3131
import static io.netty.buffer.Unpooled.unreleasableBuffer;
@@ -42,9 +42,9 @@ public final class BoltProtocolUtil
4242

4343
private static final ByteBuf HANDSHAKE_BUF = unreleasableBuffer( copyInt(
4444
BOLT_MAGIC_PREAMBLE,
45+
BoltProtocolV5.VERSION.toInt(),
4546
BoltProtocolV44.VERSION.toIntRange( BoltProtocolV42.VERSION ),
4647
BoltProtocolV41.VERSION.toInt(),
47-
BoltProtocolV4.VERSION.toInt(),
4848
BoltProtocolV3.VERSION.toInt() ) ).asReadOnly();
4949

5050
private static final String HANDSHAKE_STRING = createHandshakeString();

driver/src/main/java/org/neo4j/driver/internal/messaging/BoltProtocol.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.neo4j.driver.internal.messaging.v42.BoltProtocolV42;
4242
import org.neo4j.driver.internal.messaging.v43.BoltProtocolV43;
4343
import org.neo4j.driver.internal.messaging.v44.BoltProtocolV44;
44+
import org.neo4j.driver.internal.messaging.v5.BoltProtocolV5;
4445
import org.neo4j.driver.internal.spi.Connection;
4546

4647
import static org.neo4j.driver.internal.async.connection.ChannelAttributes.protocolVersion;
@@ -171,6 +172,10 @@ else if ( BoltProtocolV44.VERSION.equals( version ) )
171172
{
172173
return BoltProtocolV44.INSTANCE;
173174
}
175+
else if ( BoltProtocolV5.VERSION.equals( version ) )
176+
{
177+
return BoltProtocolV5.INSTANCE;
178+
}
174179
throw new ClientException( "Unknown protocol version: " + version );
175180
}
176181
}

driver/src/main/java/org/neo4j/driver/internal/messaging/common/CommonValueUnpacker.java

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ public class CommonValueUnpacker implements ValueUnpacker
9191
public static final byte UNBOUND_RELATIONSHIP = 'r';
9292
public static final byte PATH = 'P';
9393

94-
public static final int NODE_FIELDS = 3;
94+
private static final int NODE_FIELDS = 3;
95+
private static final int RELATIONSHIP_FIELDS = 5;
9596

9697
protected final PackStream.Unpacker unpacker;
9798

@@ -141,7 +142,7 @@ public Value[] unpackArray() throws IOException
141142
return values;
142143
}
143144

144-
private Value unpack() throws IOException
145+
protected Value unpack() throws IOException
145146
{
146147
PackType type = unpacker.peekNextType();
147148
switch ( type )
@@ -182,7 +183,7 @@ private Value unpack() throws IOException
182183
throw new IOException( "Unknown value type: " + type );
183184
}
184185

185-
protected Value unpackStruct( long size, byte type ) throws IOException
186+
private Value unpackStruct( long size, byte type ) throws IOException
186187
{
187188
switch ( type )
188189
{
@@ -214,11 +215,11 @@ protected Value unpackStruct( long size, byte type ) throws IOException
214215
ensureCorrectStructSize( TypeConstructor.POINT, POINT_3D_STRUCT_SIZE, size );
215216
return unpackPoint3D();
216217
case NODE:
217-
ensureCorrectStructSize( TypeConstructor.NODE, NODE_FIELDS, size );
218+
ensureCorrectStructSize( TypeConstructor.NODE, getNodeFields(), size );
218219
InternalNode adapted = unpackNode();
219220
return new NodeValue( adapted );
220221
case RELATIONSHIP:
221-
ensureCorrectStructSize( TypeConstructor.RELATIONSHIP, 5, size );
222+
ensureCorrectStructSize( TypeConstructor.RELATIONSHIP, getRelationshipFields(), size );
222223
return unpackRelationship();
223224
case PATH:
224225
ensureCorrectStructSize( TypeConstructor.PATH, 3, size );
@@ -228,19 +229,20 @@ protected Value unpackStruct( long size, byte type ) throws IOException
228229
}
229230
}
230231

231-
private Value unpackRelationship() throws IOException
232+
protected Value unpackRelationship() throws IOException
232233
{
233234
long urn = unpacker.unpackLong();
234235
long startUrn = unpacker.unpackLong();
235236
long endUrn = unpacker.unpackLong();
236237
String relType = unpacker.unpackString();
237238
Map<String,Value> props = unpackMap();
238239

239-
InternalRelationship adapted = new InternalRelationship( urn, startUrn, endUrn, relType, props );
240+
InternalRelationship adapted =
241+
new InternalRelationship( urn, String.valueOf( urn ), startUrn, String.valueOf( startUrn ), endUrn, String.valueOf( endUrn ), relType, props );
240242
return new RelationshipValue( adapted );
241243
}
242244

243-
private InternalNode unpackNode() throws IOException
245+
protected InternalNode unpackNode() throws IOException
244246
{
245247
long urn = unpacker.unpackLong();
246248

@@ -258,16 +260,16 @@ private InternalNode unpackNode() throws IOException
258260
props.put( key, unpack() );
259261
}
260262

261-
return new InternalNode( urn, labels, props );
263+
return new InternalNode( urn, String.valueOf( urn ), labels, props );
262264
}
263265

264-
private Value unpackPath() throws IOException
266+
protected Value unpackPath() throws IOException
265267
{
266268
// List of unique nodes
267269
Node[] uniqNodes = new Node[(int) unpacker.unpackListHeader()];
268270
for ( int i = 0; i < uniqNodes.length; i++ )
269271
{
270-
ensureCorrectStructSize( TypeConstructor.NODE, NODE_FIELDS, unpacker.unpackStructHeader() );
272+
ensureCorrectStructSize( TypeConstructor.NODE, getNodeFields(), unpacker.unpackStructHeader() );
271273
ensureCorrectStructSignature( "NODE", NODE, unpacker.unpackStructSignature() );
272274
uniqNodes[i] = unpackNode();
273275
}
@@ -281,7 +283,7 @@ private Value unpackPath() throws IOException
281283
long id = unpacker.unpackLong();
282284
String relType = unpacker.unpackString();
283285
Map<String,Value> props = unpackMap();
284-
uniqRels[i] = new InternalRelationship( id, -1, -1, relType, props );
286+
uniqRels[i] = new InternalRelationship( id, String.valueOf( id ), -1, String.valueOf( -1 ), -1, String.valueOf( -1 ), relType, props );
285287
}
286288

287289
// Path sequence
@@ -303,12 +305,12 @@ private Value unpackPath() throws IOException
303305
if ( relIdx < 0 )
304306
{
305307
rel = uniqRels[(-relIdx) - 1]; // -1 because rel idx are 1-indexed
306-
rel.setStartAndEnd( nextNode.id(), prevNode.id() );
308+
rel.setStartAndEnd( nextNode.id(), String.valueOf( nextNode.id() ), prevNode.id(), String.valueOf( prevNode.id() ) );
307309
}
308310
else
309311
{
310312
rel = uniqRels[relIdx - 1];
311-
rel.setStartAndEnd( prevNode.id(), nextNode.id() );
313+
rel.setStartAndEnd( prevNode.id(), String.valueOf( prevNode.id() ), nextNode.id(), String.valueOf( nextNode.id() ) );
312314
}
313315

314316
nodes[i + 1] = nextNode;
@@ -330,7 +332,7 @@ protected final void ensureCorrectStructSize( TypeConstructor typeConstructor, i
330332
}
331333
}
332334

333-
private void ensureCorrectStructSignature( String structName, byte expected, byte actual )
335+
protected void ensureCorrectStructSignature( String structName, byte expected, byte actual )
334336
{
335337
if ( expected != actual )
336338
{
@@ -417,6 +419,14 @@ private static ZonedDateTime newZonedDateTime( long epochSecondLocal, long nano,
417419
LocalDateTime localDateTime = LocalDateTime.ofInstant( instant, UTC );
418420
return ZonedDateTime.of( localDateTime, zoneId );
419421
}
420-
}
421422

423+
protected int getNodeFields()
424+
{
425+
return NODE_FIELDS;
426+
}
422427

428+
protected int getRelationshipFields()
429+
{
430+
return RELATIONSHIP_FIELDS;
431+
}
432+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.neo4j.driver.internal.messaging.v5;
20+
21+
import org.neo4j.driver.internal.messaging.BoltProtocol;
22+
import org.neo4j.driver.internal.messaging.BoltProtocolVersion;
23+
import org.neo4j.driver.internal.messaging.MessageFormat;
24+
import org.neo4j.driver.internal.messaging.v44.BoltProtocolV44;
25+
26+
public class BoltProtocolV5 extends BoltProtocolV44
27+
{
28+
public static final BoltProtocolVersion VERSION = new BoltProtocolVersion( 5, 0 );
29+
public static final BoltProtocol INSTANCE = new BoltProtocolV5();
30+
31+
@Override
32+
public MessageFormat createMessageFormat()
33+
{
34+
return new MessageFormatV5();
35+
}
36+
37+
@Override
38+
public BoltProtocolVersion version()
39+
{
40+
return VERSION;
41+
}
42+
}

0 commit comments

Comments
 (0)