Skip to content

Commit 9a5440c

Browse files
authored
Merge pull request #450 from ali-ince/2.0-bolt-v4
Add multi-database support
2 parents 066a410 + a263240 commit 9a5440c

33 files changed

+1203
-300
lines changed

src/driver.js

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,13 @@ class Driver {
109109

110110
/**
111111
* Verifies connectivity of this driver by trying to open a connection with the provided driver options.
112+
* @param {string} [db=''] the target database to verify connectivity for.
112113
* @returns {Promise<object>} promise resolved with server info or rejected with error.
113114
*/
114-
verifyConnectivity () {
115+
verifyConnectivity ({ db = '' } = {}) {
115116
const connectionProvider = this._getOrCreateConnectionProvider()
116117
const connectivityVerifier = new ConnectivityVerifier(connectionProvider)
117-
return connectivityVerifier.verify()
118+
return connectivityVerifier.verify({ db })
118119
}
119120

120121
/**
@@ -178,18 +179,29 @@ class Driver {
178179
* it is closed, the underlying connection will be released to the connection
179180
* pool and made available for others to use.
180181
*
181-
* @param {string} [mode=WRITE] the access mode of this session, allowed values are {@link READ} and {@link WRITE}.
182-
* @param {string|string[]} [bookmarkOrBookmarks=null] the initial reference or references to some previous
182+
* @param {string} [defaultAccessMode=WRITE] the access mode of this session, allowed values are {@link READ} and {@link WRITE}.
183+
* @param {string|string[]} [bookmarks=null] the initial reference or references to some previous
183184
* transactions. Value is optional and absence indicates that that the bookmarks do not exist or are unknown.
185+
* @param {string} [db=''] the database this session will connect to.
184186
* @return {Session} new session.
185187
*/
186-
session (mode, bookmarkOrBookmarks) {
187-
const sessionMode = Driver._validateSessionMode(mode)
188+
session ({
189+
defaultAccessMode = WRITE,
190+
bookmarks: bookmarkOrBookmarks,
191+
db = ''
192+
} = {}) {
193+
const sessionMode = Driver._validateSessionMode(defaultAccessMode)
188194
const connectionProvider = this._getOrCreateConnectionProvider()
189195
const bookmark = bookmarkOrBookmarks
190196
? new Bookmark(bookmarkOrBookmarks)
191197
: Bookmark.empty()
192-
return new Session(sessionMode, connectionProvider, bookmark, this._config)
198+
return new Session({
199+
mode: sessionMode,
200+
db,
201+
connectionProvider,
202+
bookmark,
203+
config: this._config
204+
})
193205
}
194206

195207
static _validateSessionMode (rawMode) {

src/internal/bolt-protocol-util.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* Copyright (c) 2002-2019 "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 { newError } from '../error'
20+
21+
/**
22+
* @param {TxConfig} txConfig the auto-commit transaction configuration.
23+
* @param {Connection} connection the connection.
24+
* @param {StreamObserver} observer the response observer.
25+
*/
26+
function assertTxConfigIsEmpty (txConfig, connection, observer) {
27+
if (txConfig && !txConfig.isEmpty()) {
28+
const error = newError(
29+
'Driver is connected to the database that does not support transaction configuration. ' +
30+
'Please upgrade to neo4j 3.5.0 or later in order to use this functionality'
31+
)
32+
33+
// unsupported API was used, consider this a fatal error for the current connection
34+
connection._handleFatalError(error)
35+
observer.onError(error)
36+
throw error
37+
}
38+
}
39+
40+
/**
41+
* Asserts that the passed-in database name is empty.
42+
* @param {string} db
43+
* @param {Connection} connection
44+
* @param {StreamObserver} observer
45+
*/
46+
function assertDbIsEmpty (db, connection, observer) {
47+
if (db) {
48+
const error = newError(
49+
'Driver is connected to the database that does not support multiple databases. ' +
50+
'Please upgrade to neo4j 4.0.0 or later in order to use this functionality'
51+
)
52+
53+
// unsupported API was used, consider this a fatal error for the current connection
54+
connection._handleFatalError(error)
55+
observer.onError(error)
56+
throw error
57+
}
58+
}
59+
60+
export { assertDbIsEmpty, assertTxConfigIsEmpty }

src/internal/bolt-protocol-v1.js

Lines changed: 21 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@
1818
*/
1919
import RequestMessage from './request-message'
2020
import * as v1 from './packstream-v1'
21-
import { newError } from '../error'
2221
import Bookmark from './bookmark'
2322
import TxConfig from './tx-config'
2423
import { ACCESS_MODE_WRITE } from './constants'
24+
import { assertDbIsEmpty, assertTxConfigIsEmpty } from './bolt-protocol-util'
2525

2626
export default class BoltProtocol {
2727
/**
@@ -78,13 +78,15 @@ export default class BoltProtocol {
7878

7979
/**
8080
* Begin an explicit transaction.
81+
* @param {StreamObserver} observer the response observer.
8182
* @param {Bookmark} bookmark the bookmark.
8283
* @param {TxConfig} txConfig the configuration.
84+
* @param {string} db the target database name.
8385
* @param {string} mode the access mode.
84-
* @param {StreamObserver} observer the response observer.
8586
*/
86-
beginTransaction (bookmark, txConfig, mode, observer) {
87+
beginTransaction (observer, { bookmark, txConfig, db, mode }) {
8788
assertTxConfigIsEmpty(txConfig, this._connection, observer)
89+
assertDbIsEmpty(db, this._connection, observer)
8890

8991
const runMessage = RequestMessage.run(
9092
'BEGIN',
@@ -103,14 +105,11 @@ export default class BoltProtocol {
103105
commitTransaction (observer) {
104106
// WRITE access mode is used as a place holder here, it has
105107
// no effect on behaviour for Bolt V1 & V2
106-
this.run(
107-
'COMMIT',
108-
{},
109-
Bookmark.empty(),
110-
TxConfig.empty(),
111-
ACCESS_MODE_WRITE,
112-
observer
113-
)
108+
this.run('COMMIT', {}, observer, {
109+
bookmark: Bookmark.empty(),
110+
txConfig: TxConfig.empty(),
111+
mode: ACCESS_MODE_WRITE
112+
})
114113
}
115114

116115
/**
@@ -120,28 +119,28 @@ export default class BoltProtocol {
120119
rollbackTransaction (observer) {
121120
// WRITE access mode is used as a place holder here, it has
122121
// no effect on behaviour for Bolt V1 & V2
123-
this.run(
124-
'ROLLBACK',
125-
{},
126-
Bookmark.empty(),
127-
TxConfig.empty(),
128-
ACCESS_MODE_WRITE,
129-
observer
130-
)
122+
this.run('ROLLBACK', {}, observer, {
123+
bookmark: Bookmark.empty(),
124+
txConfig: TxConfig.empty(),
125+
mode: ACCESS_MODE_WRITE
126+
})
131127
}
132128

133129
/**
134130
* Send a Cypher statement through the underlying connection.
135131
* @param {string} statement the cypher statement.
136132
* @param {object} parameters the statement parameters.
133+
* @param {StreamObserver} observer the response observer.
137134
* @param {Bookmark} bookmark the bookmark.
138135
* @param {TxConfig} txConfig the auto-commit transaction configuration.
136+
* @param {string} db the target database name.
139137
* @param {string} mode the access mode.
140-
* @param {StreamObserver} observer the response observer.
141138
*/
142-
run (statement, parameters, bookmark, txConfig, mode, observer) {
143-
// bookmark and mode are ignored in this versioon of the protocol
139+
run (statement, parameters, observer, { bookmark, txConfig, db, mode }) {
140+
// bookmark and mode are ignored in this version of the protocol
144141
assertTxConfigIsEmpty(txConfig, this._connection, observer)
142+
// passing in a db name on this protocol version throws an error
143+
assertDbIsEmpty(db, this._connection, observer)
145144

146145
const runMessage = RequestMessage.run(statement, parameters)
147146
const pullAllMessage = RequestMessage.pullAll()
@@ -167,22 +166,3 @@ export default class BoltProtocol {
167166
return new v1.Unpacker(disableLosslessIntegers)
168167
}
169168
}
170-
171-
/**
172-
* @param {TxConfig} txConfig the auto-commit transaction configuration.
173-
* @param {Connection} connection the connection.
174-
* @param {StreamObserver} observer the response observer.
175-
*/
176-
function assertTxConfigIsEmpty (txConfig, connection, observer) {
177-
if (!txConfig.isEmpty()) {
178-
const error = newError(
179-
'Driver is connected to the database that does not support transaction configuration. ' +
180-
'Please upgrade to neo4j 3.5.0 or later in order to use this functionality'
181-
)
182-
183-
// unsupported API was used, consider this a fatal error for the current connection
184-
connection._handleFatalError(error)
185-
observer.onError(error)
186-
throw error
187-
}
188-
}

src/internal/bolt-protocol-v3.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
import BoltProtocolV2 from './bolt-protocol-v2'
2020
import RequestMessage from './request-message'
21+
import { assertDbIsEmpty } from './bolt-protocol-util'
2122

2223
export default class BoltProtocol extends BoltProtocolV2 {
2324
transformMetadata (metadata) {
@@ -47,9 +48,10 @@ export default class BoltProtocol extends BoltProtocolV2 {
4748
this._connection.write(message, observer, true)
4849
}
4950

50-
beginTransaction (bookmark, txConfig, mode, observer) {
51+
beginTransaction (observer, { bookmark, txConfig, db, mode }) {
52+
assertDbIsEmpty(db, this._connection, observer)
5153
prepareToHandleSingleResponse(observer)
52-
const message = RequestMessage.begin(bookmark, txConfig, mode)
54+
const message = RequestMessage.begin({ bookmark, txConfig, mode })
5355
this._connection.write(message, observer, true)
5456
}
5557

@@ -65,14 +67,15 @@ export default class BoltProtocol extends BoltProtocolV2 {
6567
this._connection.write(message, observer, true)
6668
}
6769

68-
run (statement, parameters, bookmark, txConfig, mode, observer) {
69-
const runMessage = RequestMessage.runWithMetadata(
70-
statement,
71-
parameters,
70+
run (statement, parameters, observer, { bookmark, txConfig, db, mode }) {
71+
// passing in a db name on this protocol version throws an error
72+
assertDbIsEmpty(db, this._connection, observer)
73+
74+
const runMessage = RequestMessage.runWithMetadata(statement, parameters, {
7275
bookmark,
7376
txConfig,
7477
mode
75-
)
78+
})
7679
const pullAllMessage = RequestMessage.pullAll()
7780

7881
this._connection.write(runMessage, observer, false)

src/internal/bolt-protocol-v4.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* Copyright (c) 2002-2019 "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 BoltProtocolV3 from './bolt-protocol-v3'
20+
import RequestMessage from './request-message'
21+
22+
export default class BoltProtocol extends BoltProtocolV3 {
23+
beginTransaction (observer, { bookmark, txConfig, db, mode }) {
24+
const message = RequestMessage.begin({ bookmark, txConfig, db, mode })
25+
this._connection.write(message, observer, true)
26+
}
27+
28+
run (statement, parameters, observer, { bookmark, txConfig, db, mode }) {
29+
const runMessage = RequestMessage.runWithMetadata(statement, parameters, {
30+
bookmark,
31+
txConfig,
32+
db,
33+
mode
34+
})
35+
const pullMessage = RequestMessage.pull()
36+
37+
this._connection.write(runMessage, observer, false)
38+
this._connection.write(pullMessage, observer, true)
39+
}
40+
}

src/internal/connection-holder.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
*/
1919

2020
import { newError } from '../error'
21+
import { assertString } from './util'
22+
import { ACCESS_MODE_WRITE } from './constants'
2123

2224
/**
2325
* Utility to lazily initialize connections and return them back to the pool when unused.
@@ -26,10 +28,12 @@ export default class ConnectionHolder {
2628
/**
2729
* @constructor
2830
* @param {string} mode - the access mode for new connection holder.
31+
* @param {string} db - the target database name.
2932
* @param {ConnectionProvider} connectionProvider - the connection provider to acquire connections from.
3033
*/
31-
constructor (mode, connectionProvider) {
34+
constructor ({ mode = ACCESS_MODE_WRITE, db = '', connectionProvider } = {}) {
3235
this._mode = mode
36+
this._db = db ? assertString(db, 'db') : ''
3337
this._connectionProvider = connectionProvider
3438
this._referenceCount = 0
3539
this._connectionPromise = Promise.resolve(null)
@@ -43,14 +47,23 @@ export default class ConnectionHolder {
4347
return this._mode
4448
}
4549

50+
/**
51+
* Returns the target database name
52+
* @returns {string} db name
53+
*/
54+
db () {
55+
return this._db
56+
}
57+
4658
/**
4759
* Make this holder initialize new connection if none exists already.
4860
* @return {undefined}
4961
*/
5062
initializeConnection () {
5163
if (this._referenceCount === 0) {
5264
this._connectionPromise = this._connectionProvider.acquireConnection(
53-
this._mode
65+
this._mode,
66+
this._db
5467
)
5568
}
5669
this._referenceCount++

0 commit comments

Comments
 (0)