Skip to content

Add support for Bolt 5 #1181

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 17, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions driver/clirr-ignored-differences.xml
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,22 @@
<to>org.neo4j.driver.Config$TrustStrategy trustCustomCertificateSignedBy(java.io.File[])</to>
</difference>

<difference>
<className>org/neo4j/driver/types/Entity</className>
<differenceType>7012</differenceType>
<method>java.lang.String elementId()</method>
</difference>

<difference>
<className>org/neo4j/driver/types/Relationship</className>
<differenceType>7012</differenceType>
<method>java.lang.String endNodeElementId()</method>
</difference>

<difference>
<className>org/neo4j/driver/types/Relationship</className>
<differenceType>7012</differenceType>
<method>java.lang.String startNodeElementId()</method>
</difference>

</differences>
16 changes: 12 additions & 4 deletions driver/src/main/java/org/neo4j/driver/internal/InternalEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,27 @@
package org.neo4j.driver.internal;

import java.util.Map;
import java.util.function.Function;

import org.neo4j.driver.Value;
import org.neo4j.driver.Values;
import org.neo4j.driver.internal.util.Extract;
import org.neo4j.driver.internal.util.Iterables;
import org.neo4j.driver.internal.value.MapValue;
import org.neo4j.driver.Value;
import org.neo4j.driver.Values;
import org.neo4j.driver.types.Entity;
import java.util.function.Function;

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

public abstract class InternalEntity implements Entity, AsValue
{
private final long id;
private final String elementId;
private final Map<String,Value> properties;

public InternalEntity( long id, Map<String, Value> properties )
public InternalEntity( long id, String elementId, Map<String,Value> properties )
{
this.id = id;
this.elementId = elementId;
this.properties = properties;
}

Expand All @@ -47,6 +49,12 @@ public long id()
return id;
}

@Override
public String elementId()
{
return elementId;
}

@Override
public int size()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
import java.util.Collections;
import java.util.Map;

import org.neo4j.driver.Value;
import org.neo4j.driver.internal.value.NodeValue;
import org.neo4j.driver.types.Node;
import org.neo4j.driver.Value;

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

public InternalNode( long id )
{
this( id, Collections.<String>emptyList(), Collections.<String,Value>emptyMap() );
this( id, String.valueOf( id ), Collections.emptyList(), Collections.emptyMap() );
}

public InternalNode( long id, Collection<String> labels, Map<String, Value> properties )
public InternalNode( long id, String elementId, Collection<String> labels, Map<String,Value> properties )
{
super( id, properties );
super( id, elementId, properties );
this.labels = labels;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,30 +21,34 @@
import java.util.Collections;
import java.util.Map;

import org.neo4j.driver.Value;
import org.neo4j.driver.internal.value.RelationshipValue;
import org.neo4j.driver.types.Relationship;
import org.neo4j.driver.Value;

/**
* {@link Relationship} implementation that directly contains type and properties.
*/
public class InternalRelationship extends InternalEntity implements Relationship
{
private long start;
private String startElementId;
private long end;
private String endElementId;
private final String type;

public InternalRelationship( long id, long start, long end, String type )
public InternalRelationship( long id, String elementId, long start, String startElementId, long end, String endElementId, String type )
{
this( id, start, end, type, Collections.<String,Value>emptyMap() );
this( id, elementId, start, startElementId, end, endElementId, type, Collections.emptyMap() );
}

public InternalRelationship( long id, long start, long end, String type,
Map<String, Value> properties )
public InternalRelationship( long id, String elementId, long start, String startElementId, long end, String endElementId, String type,
Map<String,Value> properties )
{
super( id, properties );
super( id, elementId, properties );
this.start = start;
this.startElementId = startElementId;
this.end = end;
this.endElementId = endElementId;
this.type = type;
}

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

/** Modify the start/end identities of this relationship */
public void setStartAndEnd( long start, long end )
/**
* Modify the start/end identities of this relationship
*/
public void setStartAndEnd( long start, String startElementId, long end, String endElementId )
{
this.start = start;
this.startElementId = startElementId;
this.end = end;
this.endElementId = endElementId;
}

@Override
Expand All @@ -67,12 +75,24 @@ public long startNodeId()
return start;
}

@Override
public String startNodeElementId()
{
return startElementId;
}

@Override
public long endNodeId()
{
return end;
}

@Override
public String endNodeElementId()
{
return endElementId;
}

@Override
public String type()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@

import org.neo4j.driver.internal.messaging.BoltProtocolVersion;
import org.neo4j.driver.internal.messaging.v3.BoltProtocolV3;
import org.neo4j.driver.internal.messaging.v4.BoltProtocolV4;
import org.neo4j.driver.internal.messaging.v41.BoltProtocolV41;
import org.neo4j.driver.internal.messaging.v42.BoltProtocolV42;
import org.neo4j.driver.internal.messaging.v44.BoltProtocolV44;
import org.neo4j.driver.internal.messaging.v5.BoltProtocolV5;

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

private static final ByteBuf HANDSHAKE_BUF = unreleasableBuffer( copyInt(
BOLT_MAGIC_PREAMBLE,
BoltProtocolV5.VERSION.toInt(),
BoltProtocolV44.VERSION.toIntRange( BoltProtocolV42.VERSION ),
BoltProtocolV41.VERSION.toInt(),
BoltProtocolV4.VERSION.toInt(),
BoltProtocolV3.VERSION.toInt() ) ).asReadOnly();

private static final String HANDSHAKE_STRING = createHandshakeString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import org.neo4j.driver.internal.messaging.v42.BoltProtocolV42;
import org.neo4j.driver.internal.messaging.v43.BoltProtocolV43;
import org.neo4j.driver.internal.messaging.v44.BoltProtocolV44;
import org.neo4j.driver.internal.messaging.v5.BoltProtocolV5;
import org.neo4j.driver.internal.spi.Connection;

import static org.neo4j.driver.internal.async.connection.ChannelAttributes.protocolVersion;
Expand Down Expand Up @@ -171,6 +172,10 @@ else if ( BoltProtocolV44.VERSION.equals( version ) )
{
return BoltProtocolV44.INSTANCE;
}
else if ( BoltProtocolV5.VERSION.equals( version ) )
{
return BoltProtocolV5.INSTANCE;
}
throw new ClientException( "Unknown protocol version: " + version );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ public Value[] unpackArray() throws IOException
return values;
}

private Value unpack() throws IOException
protected Value unpack() throws IOException
{
PackType type = unpacker.peekNextType();
switch ( type )
Expand Down Expand Up @@ -182,7 +182,7 @@ private Value unpack() throws IOException
throw new IOException( "Unknown value type: " + type );
}

protected Value unpackStruct( long size, byte type ) throws IOException
private Value unpackStruct( long size, byte type ) throws IOException
{
switch ( type )
{
Expand Down Expand Up @@ -214,11 +214,11 @@ protected Value unpackStruct( long size, byte type ) throws IOException
ensureCorrectStructSize( TypeConstructor.POINT, POINT_3D_STRUCT_SIZE, size );
return unpackPoint3D();
case NODE:
ensureCorrectStructSize( TypeConstructor.NODE, NODE_FIELDS, size );
ensureCorrectStructSize( TypeConstructor.NODE, getNodeFields(), size );
InternalNode adapted = unpackNode();
return new NodeValue( adapted );
case RELATIONSHIP:
ensureCorrectStructSize( TypeConstructor.RELATIONSHIP, 5, size );
ensureCorrectStructSize( TypeConstructor.RELATIONSHIP, getRelationshipFields(), size );
return unpackRelationship();
case PATH:
ensureCorrectStructSize( TypeConstructor.PATH, 3, size );
Expand All @@ -228,19 +228,20 @@ protected Value unpackStruct( long size, byte type ) throws IOException
}
}

private Value unpackRelationship() throws IOException
protected Value unpackRelationship() throws IOException
{
long urn = unpacker.unpackLong();
long startUrn = unpacker.unpackLong();
long endUrn = unpacker.unpackLong();
String relType = unpacker.unpackString();
Map<String,Value> props = unpackMap();

InternalRelationship adapted = new InternalRelationship( urn, startUrn, endUrn, relType, props );
InternalRelationship adapted =
new InternalRelationship( urn, String.valueOf( urn ), startUrn, String.valueOf( startUrn ), endUrn, String.valueOf( endUrn ), relType, props );
return new RelationshipValue( adapted );
}

private InternalNode unpackNode() throws IOException
protected InternalNode unpackNode() throws IOException
{
long urn = unpacker.unpackLong();

Expand All @@ -258,16 +259,16 @@ private InternalNode unpackNode() throws IOException
props.put( key, unpack() );
}

return new InternalNode( urn, labels, props );
return new InternalNode( urn, String.valueOf( urn ), labels, props );
}

private Value unpackPath() throws IOException
protected Value unpackPath() throws IOException
{
// List of unique nodes
Node[] uniqNodes = new Node[(int) unpacker.unpackListHeader()];
for ( int i = 0; i < uniqNodes.length; i++ )
{
ensureCorrectStructSize( TypeConstructor.NODE, NODE_FIELDS, unpacker.unpackStructHeader() );
ensureCorrectStructSize( TypeConstructor.NODE, getNodeFields(), unpacker.unpackStructHeader() );
ensureCorrectStructSignature( "NODE", NODE, unpacker.unpackStructSignature() );
uniqNodes[i] = unpackNode();
}
Expand All @@ -281,7 +282,7 @@ private Value unpackPath() throws IOException
long id = unpacker.unpackLong();
String relType = unpacker.unpackString();
Map<String,Value> props = unpackMap();
uniqRels[i] = new InternalRelationship( id, -1, -1, relType, props );
uniqRels[i] = new InternalRelationship( id, String.valueOf( id ), -1, String.valueOf( -1 ), -1, String.valueOf( -1 ), relType, props );
}

// Path sequence
Expand All @@ -303,12 +304,12 @@ private Value unpackPath() throws IOException
if ( relIdx < 0 )
{
rel = uniqRels[(-relIdx) - 1]; // -1 because rel idx are 1-indexed
rel.setStartAndEnd( nextNode.id(), prevNode.id() );
rel.setStartAndEnd( nextNode.id(), String.valueOf( nextNode.id() ), prevNode.id(), String.valueOf( prevNode.id() ) );
}
else
{
rel = uniqRels[relIdx - 1];
rel.setStartAndEnd( prevNode.id(), nextNode.id() );
rel.setStartAndEnd( prevNode.id(), String.valueOf( prevNode.id() ), nextNode.id(), String.valueOf( nextNode.id() ) );
}

nodes[i + 1] = nextNode;
Expand All @@ -330,7 +331,7 @@ protected final void ensureCorrectStructSize( TypeConstructor typeConstructor, i
}
}

private void ensureCorrectStructSignature( String structName, byte expected, byte actual )
protected void ensureCorrectStructSignature( String structName, byte expected, byte actual )
{
if ( expected != actual )
{
Expand Down Expand Up @@ -417,6 +418,14 @@ private static ZonedDateTime newZonedDateTime( long epochSecondLocal, long nano,
LocalDateTime localDateTime = LocalDateTime.ofInstant( instant, UTC );
return ZonedDateTime.of( localDateTime, zoneId );
}
}

protected int getNodeFields()
{
return NODE_FIELDS;
}

protected int getRelationshipFields()
{
return 5;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.neo4j.driver.internal.messaging.v5;

import org.neo4j.driver.internal.messaging.BoltProtocol;
import org.neo4j.driver.internal.messaging.BoltProtocolVersion;
import org.neo4j.driver.internal.messaging.MessageFormat;
import org.neo4j.driver.internal.messaging.v44.BoltProtocolV44;

public class BoltProtocolV5 extends BoltProtocolV44
{
public static final BoltProtocolVersion VERSION = new BoltProtocolVersion( 5, 0 );
public static final BoltProtocol INSTANCE = new BoltProtocolV5();

@Override
public MessageFormat createMessageFormat()
{
return new MessageFormatV5();
}

@Override
public BoltProtocolVersion version()
{
return VERSION;
}
}
Loading