Skip to content

Commit 88c07fd

Browse files
authored
Enabling BoltProtocol v5 and the new elementId in the graph types (#884)
The format of the identifiers used by the kernel is changing from the current long that represents a file offset to a more flexible format needed by the new Freki storage engine. In 5.0 the new storage engine will be ‘off’ by default, at some point in the future it will be enabled by default. The drivers will need to be able to support the old format alongside the new one in 5.0. To do this the existing long will remain and a new parallel identifier will be added that is of type string. The new string version will contain the long value for servers using the older non Freki storage engine e.g. versions < 5.0 and versions 5.x with Freki disabled. The following changes in the graph types was done for accommodating the elementId: - in `Node`: - Add `elementId: string` for identifying the element; - Deprecate `identity: NumberOrInteger` - in `Relationship`: - Add `elementId: string` for identifying the element; - Deprecate `identity: NumberOrInteger` - Add `startNodeElementId: string` for identifying the start node; - Deprecate `start: NumberOrInteger` - Add `endNodeElementId: string` for identifying the end node; - Deprecate `end: NumberOrInteger` - in `UnboundRelationship`: - Add `elementId: string` for identifying the element; - Deprecate `identity: NumberOrInteger`
1 parent 2f894c7 commit 88c07fd

File tree

16 files changed

+1575
-31
lines changed

16 files changed

+1575
-31
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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+
import BoltProtocolV44 from './bolt-protocol-v4x4'
20+
import { v5 } from '../packstream'
21+
22+
import { internal } from 'neo4j-driver-core'
23+
24+
const {
25+
constants: { BOLT_PROTOCOL_V5_0 },
26+
} = internal
27+
28+
export default class BoltProtocol extends BoltProtocolV44 {
29+
get version() {
30+
return BOLT_PROTOCOL_V5_0
31+
}
32+
33+
_createPacker (chunker) {
34+
return new v5.Packer(chunker)
35+
}
36+
37+
_createUnpacker (disableLosslessIntegers, useBigInt) {
38+
return new v5.Unpacker(disableLosslessIntegers, useBigInt)
39+
}
40+
}

packages/bolt-connection/src/bolt/create.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import BoltProtocolV4x1 from './bolt-protocol-v4x1'
2626
import BoltProtocolV4x2 from './bolt-protocol-v4x2'
2727
import BoltProtocolV4x3 from './bolt-protocol-v4x3'
2828
import BoltProtocolV4x4 from './bolt-protocol-v4x4'
29+
import BoltProtocolV5x0 from './bolt-protocol-v5x0'
2930
import { Chunker, Dechunker } from '../channel'
3031
import ResponseHandler from './response-handler'
3132

@@ -175,6 +176,16 @@ function createProtocol (
175176
onProtocolError,
176177
serversideRouting
177178
)
179+
case 5.0:
180+
return new BoltProtocolV5x0(
181+
server,
182+
chunker,
183+
packingConfig,
184+
createResponseHandler,
185+
log,
186+
onProtocolError,
187+
serversideRouting
188+
)
178189
default:
179190
throw newError('Unknown Bolt protocol version: ' + version)
180191
}

packages/bolt-connection/src/bolt/handshake.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ function parseNegotiatedResponse (buffer) {
7676
*/
7777
function newHandshakeBuffer () {
7878
return createHandshakeMessage([
79+
version(5, 0),
7980
[version(4, 4), version(4, 2)],
8081
version(4, 1),
81-
version(4, 0),
8282
version(3, 0)
8383
])
8484
}

packages/bolt-connection/src/packstream/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919

2020
import * as v1 from './packstream-v1'
2121
import * as v2 from './packstream-v2'
22+
import * as v5 from './packstream-v5'
2223

23-
export { v1, v2 }
24+
export { v1, v2, v5 }
2425

2526
export default v2

packages/bolt-connection/src/packstream/packstream-v1.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -646,18 +646,18 @@ class Unpacker {
646646
// information about their start and end nodes, that's instead
647647
// inferred from the path sequence. This is us inferring (and,
648648
// for performance reasons remembering) the start/end of a rel.
649-
rels[relIndex - 1] = rel = rel.bind(
650-
prevNode.identity,
651-
nextNode.identity
649+
rels[relIndex - 1] = rel = rel.bindTo(
650+
prevNode,
651+
nextNode
652652
)
653653
}
654654
} else {
655655
rel = rels[-relIndex - 1]
656656
if (rel instanceof UnboundRelationship) {
657657
// See above
658-
rels[-relIndex - 1] = rel = rel.bind(
659-
nextNode.identity,
660-
prevNode.identity
658+
rels[-relIndex - 1] = rel = rel.bindTo(
659+
nextNode,
660+
prevNode
661661
)
662662
}
663663
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
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+
20+
import * as v2 from './packstream-v2'
21+
import {
22+
Node,
23+
Relationship,
24+
UnboundRelationship,
25+
int
26+
} from 'neo4j-driver-core'
27+
28+
const NODE_STRUCT_SIZE = 4
29+
const RELATIONSHIP_STRUCT_SIZE = 8
30+
const UNBOUND_RELATIONSHIP_STRUCT_SIZE = 4
31+
32+
export class Packer extends v2.Packer {
33+
// This implementation is the same
34+
}
35+
36+
export class Unpacker extends v2.Unpacker {
37+
/**
38+
* @constructor
39+
* @param {boolean} disableLosslessIntegers if this unpacker should convert all received integers to native JS numbers.
40+
* @param {boolean} useBigInt if this unpacker should convert all received integers to Bigint
41+
*/
42+
constructor (disableLosslessIntegers = false, useBigInt = false) {
43+
this._disableLosslessIntegers = disableLosslessIntegers
44+
this._useBigInt = useBigInt
45+
this._defaultIdentity = this._getDefaultIdentity()
46+
}
47+
48+
_getDefaultIdentity() {
49+
if (this._useBigInt) {
50+
return BigInt(-1)
51+
} else if (this._disableLosslessIntegers) {
52+
return -1
53+
} else {
54+
return int(-1)
55+
}
56+
}
57+
58+
_unpackNode (structSize, buffer) {
59+
this._verifyStructSize('Node', NODE_STRUCT_SIZE, structSize)
60+
61+
return new Node(
62+
_valueOrDefault(this.unpack(buffer), this._defaultIdentity), // Identity
63+
this.unpack(buffer), // Labels
64+
this.unpack(buffer), // Properties,
65+
this.unpack(buffer) // ElementId
66+
)
67+
}
68+
69+
_unpackRelationship (structSize, buffer) {
70+
this._verifyStructSize('Relationship', RELATIONSHIP_STRUCT_SIZE, structSize)
71+
72+
return new Relationship(
73+
_valueOrDefault(this.unpack(buffer), this._defaultIdentity), // Identity
74+
_valueOrDefault(this.unpack(buffer), this._defaultIdentity), // Start Node Identity
75+
_valueOrDefault(this.unpack(buffer), this._defaultIdentity), // End Node Identity
76+
this.unpack(buffer), // Type
77+
this.unpack(buffer), // Properties,
78+
this.unpack(buffer), // ElementId
79+
this.unpack(buffer), // Start Node Element Id
80+
this.unpack(buffer) // End Node Element Id
81+
)
82+
}
83+
84+
_unpackUnboundRelationship (structSize, buffer) {
85+
this._verifyStructSize(
86+
'UnboundRelationship',
87+
UNBOUND_RELATIONSHIP_STRUCT_SIZE,
88+
structSize
89+
)
90+
91+
return new UnboundRelationship(
92+
_valueOrDefault(this.unpack(buffer), this._defaultIdentity), // Identity
93+
this.unpack(buffer), // Type
94+
this.unpack(buffer), // Properties
95+
this.unpack(buffer) // ElementId
96+
)
97+
}
98+
}
99+
100+
function _valueOrDefault(value, defaultValue) {
101+
return value === null ? defaultValue : value
102+
}

0 commit comments

Comments
 (0)