diff --git a/e2e_tests/integration/multi-db.spec.js b/e2e_tests/integration/multi-db.spec.js
index dc0fda213cb..10f9c0ccb1b 100644
--- a/e2e_tests/integration/multi-db.spec.js
+++ b/e2e_tests/integration/multi-db.spec.js
@@ -212,5 +212,38 @@ describe('Multi database', () => {
.first()
resultFrame.should('contain', 'could not be found')
})
+ if (isEnterpriseEdition()) {
+ it('re-runs query from frame action button on original db', () => {
+ cy.executeCommand(':clear')
+ cy.executeCommand(':use neo4j')
+ cy.executeCommand(':clear')
+ cy.executeCommand('RETURN "Test string"')
+ cy.executeCommand(':use system')
+
+ // Close first frame
+ cy.get('[title="Close"]', { timeout: 10000 })
+ .first()
+ .click()
+
+ // Make sure it's closed
+ cy.get('[data-testid="frame"]', { timeout: 10000 }).should(
+ 'have.length',
+ 1
+ )
+
+ // Click re-run
+ cy.get('[data-testid="rerunFrameButton"]', { timeout: 10000 })
+ .first()
+ .click()
+
+ // Make sure we have what we expect
+ cy.get('[data-testid="frame"]', { timeout: 10000 })
+ .first()
+ .should(frame => {
+ expect(frame).to.contain('"Test string"')
+ expect(frame).to.not.contain('ERROR')
+ })
+ })
+ }
}
})
diff --git a/src/browser/modules/DecoratedText/TextCommand.jsx b/src/browser/modules/DecoratedText/TextCommand.jsx
index 8690620ad17..713faf8ccad 100644
--- a/src/browser/modules/DecoratedText/TextCommand.jsx
+++ b/src/browser/modules/DecoratedText/TextCommand.jsx
@@ -64,4 +64,7 @@ const mapDispatchToProps = dispatch => {
}
}
-export default connect(mapStateToProps, mapDispatchToProps)(TextCommand)
+export default connect(
+ mapStateToProps,
+ mapDispatchToProps
+)(TextCommand)
diff --git a/src/browser/modules/Frame/FrameTitlebar.jsx b/src/browser/modules/Frame/FrameTitlebar.jsx
index f07c3d3f0d2..ecba1059c0d 100644
--- a/src/browser/modules/Frame/FrameTitlebar.jsx
+++ b/src/browser/modules/Frame/FrameTitlebar.jsx
@@ -252,9 +252,7 @@ class FrameTitlebar extends Component {
- props.onReRunClick(frame.cmd, frame.id, frame.requestId)
- }
+ onClick={() => props.onReRunClick(frame)}
>
@@ -295,11 +293,11 @@ const mapDispatchToProps = (dispatch, ownProps) => {
}
dispatch(remove(id))
},
- onReRunClick: (cmd, id, requestId) => {
+ onReRunClick: ({ cmd, useDb, id, requestId }) => {
if (requestId) {
dispatch(cancelRequest(requestId))
}
- dispatch(commands.executeCommand(cmd, id))
+ dispatch(commands.executeCommand(cmd, { id, useDb }))
},
togglePinning: (id, isPinned) => {
isPinned ? dispatch(unpin(id)) : dispatch(pin(id))
@@ -308,5 +306,8 @@ const mapDispatchToProps = (dispatch, ownProps) => {
}
export default withBus(
- connect(mapStateToProps, mapDispatchToProps)(FrameTitlebar)
+ connect(
+ mapStateToProps,
+ mapDispatchToProps
+ )(FrameTitlebar)
)
diff --git a/src/browser/modules/Stream/StyleFrame.jsx b/src/browser/modules/Stream/StyleFrame.jsx
index 0eadf5a344f..fe28bdd5205 100644
--- a/src/browser/modules/Stream/StyleFrame.jsx
+++ b/src/browser/modules/Stream/StyleFrame.jsx
@@ -83,7 +83,9 @@ const StyleStatusbar = ({ resetStyleAction, rerunAction, onResetClick }) => {
const mapStateToProps = (state, ownProps) => {
return {
resetStyleAction: executeSystemCommand(`${getCmdChar(state)}style reset`),
- rerunAction: executeCommand(ownProps.frame.cmd, ownProps.frame.id)
+ rerunAction: executeCommand(ownProps.frame.cmd, {
+ id: ownProps.frame.id
+ })
}
}
const mapDispatchToProps = dispatch => ({
@@ -93,6 +95,9 @@ const mapDispatchToProps = dispatch => ({
}
})
-const Statusbar = connect(mapStateToProps, mapDispatchToProps)(StyleStatusbar)
+const Statusbar = connect(
+ mapStateToProps,
+ mapDispatchToProps
+)(StyleStatusbar)
export default StyleFrame
diff --git a/src/shared/modules/commands/commandsDuck.js b/src/shared/modules/commands/commandsDuck.js
index 8ef579da812..4cad1fd847e 100644
--- a/src/shared/modules/commands/commandsDuck.js
+++ b/src/shared/modules/commands/commandsDuck.js
@@ -91,22 +91,27 @@ export default function reducer(state = initialState, action) {
// Action creators
-export const executeCommand = (cmd, id, requestId, parentId) => {
+export const executeCommand = (
+ cmd,
+ { id, requestId, parentId, useDb } = {}
+) => {
return {
type: COMMAND_QUEUED,
cmd,
id,
requestId,
- parentId
+ parentId,
+ useDb
}
}
-export const executeSingleCommand = (cmd, id, requestId) => {
+export const executeSingleCommand = (cmd, { id, requestId, useDb } = {}) => {
return {
type: SINGLE_COMMAND_QUEUED,
cmd,
id,
- requestId
+ requestId,
+ useDb
}
}
@@ -162,7 +167,11 @@ export const handleCommandEpic = (action$, store) =>
if (statements.length === 1) {
// Single command
return store.dispatch(
- executeSingleCommand(statements[0], action.id, action.requestId)
+ executeSingleCommand(statements[0], {
+ id: action.id,
+ requestId: action.requestId,
+ useDb: action.useDb
+ })
)
}
const parentId = action.parentId || v4()
diff --git a/src/shared/modules/commands/commandsDuck.test.js b/src/shared/modules/commands/commandsDuck.test.js
index b88e8cd3c83..687089f423c 100644
--- a/src/shared/modules/commands/commandsDuck.test.js
+++ b/src/shared/modules/commands/commandsDuck.test.js
@@ -91,7 +91,10 @@ describe('commandsDuck', () => {
const cmd = 'RETURN 1'
const id = 2
const requestId = 'xxx'
- const action = commands.executeSingleCommand(cmd, id, requestId)
+ const action = commands.executeSingleCommand(cmd, {
+ id,
+ requestId
+ })
bus.take('NOOP', currentAction => {
// Then
expect(store.getActions()).toEqual([
@@ -138,7 +141,9 @@ describe('commandsDuck', () => {
const cmd = store.getState().settings.cmdchar + 'param'
const cmdString = cmd + ' x: 2'
const id = 1
- const action = commands.executeSingleCommand(cmdString, id)
+ const action = commands.executeSingleCommand(cmdString, {
+ id
+ })
bus.take('NOOP', currentAction => {
// Then
@@ -172,7 +177,9 @@ describe('commandsDuck', () => {
const cmd = store.getState().settings.cmdchar + 'param'
const cmdString = cmd + ' x => 2'
const id = 1
- const action = commands.executeSingleCommand(cmdString, id)
+ const action = commands.executeSingleCommand(cmdString, {
+ id
+ })
bolt.routedWriteTransaction = jest.fn(() =>
Promise.resolve({
records: [{ get: () => 2 }]
@@ -205,7 +212,9 @@ describe('commandsDuck', () => {
const cmd = store.getState().settings.cmdchar + 'params'
const cmdString = cmd + ' {x: 2, y: 3}'
const id = 1
- const action = commands.executeSingleCommand(cmdString, id)
+ const action = commands.executeSingleCommand(cmdString, {
+ id
+ })
bus.take('NOOP', currentAction => {
// Then
expect(store.getActions()).toEqual([
@@ -232,7 +241,9 @@ describe('commandsDuck', () => {
// Given
const cmdString = store.getState().settings.cmdchar + 'params'
const id = 1
- const action = commands.executeSingleCommand(cmdString, id)
+ const action = commands.executeSingleCommand(cmdString, {
+ id
+ })
bus.take('NOOP', currentAction => {
// Then
expect(store.getActions()).toEqual([
@@ -254,7 +265,9 @@ describe('commandsDuck', () => {
const cmd = store.getState().settings.cmdchar + 'config'
const cmdString = cmd + ' "x": 2'
const id = 1
- const action = commands.executeSingleCommand(cmdString, id)
+ const action = commands.executeSingleCommand(cmdString, {
+ id
+ })
bus.take('NOOP', currentAction => {
// Then
expect(store.getActions()).toEqual([
@@ -281,7 +294,9 @@ describe('commandsDuck', () => {
const cmd = store.getState().settings.cmdchar + 'config'
const cmdString = cmd + ' {"x": 2, "y":3}'
const id = 1
- const action = commands.executeSingleCommand(cmdString, id)
+ const action = commands.executeSingleCommand(cmdString, {
+ id
+ })
bus.take('NOOP', currentAction => {
// Then
expect(store.getActions()).toEqual([
@@ -309,7 +324,9 @@ describe('commandsDuck', () => {
const cmd = store.getState().settings.cmdchar + 'config'
const cmdString = cmd
const id = 1
- const action = commands.executeSingleCommand(cmdString, id)
+ const action = commands.executeSingleCommand(cmdString, {
+ id
+ })
bus.take('NOOP', currentAction => {
// Then
expect(store.getActions()).toEqual([
@@ -336,7 +353,9 @@ describe('commandsDuck', () => {
const cmd = store.getState().settings.cmdchar + 'style'
const cmdString = cmd
const id = 1
- const action = commands.executeSingleCommand(cmdString, id)
+ const action = commands.executeSingleCommand(cmdString, {
+ id
+ })
bus.take('NOOP', currentAction => {
// Then
expect(store.getActions()).toEqual([
@@ -361,7 +380,7 @@ describe('commandsDuck', () => {
test('does the right thing for list queries', done => {
const cmd = store.getState().settings.cmdchar + 'queries'
const id = 1
- const action = commands.executeSingleCommand(cmd, id)
+ const action = commands.executeSingleCommand(cmd, { id })
bus.take('NOOP', currentAction => {
expect(store.getActions()).toEqual([
@@ -385,7 +404,10 @@ describe('commandsDuck', () => {
const cmd = comment + '\n' + actualCommand
const id = 2
const requestId = 'xxx'
- const action = commands.executeSingleCommand(cmd, id, requestId)
+ const action = commands.executeSingleCommand(cmd, {
+ id,
+ requestId
+ })
bus.take('NOOP', currentAction => {
// Then
expect(store.getActions()).toEqual([
@@ -413,7 +435,7 @@ describe('commandsDuck', () => {
const cmdString = 'history'
const cmd = comment + '\n' + store.getState().settings.cmdchar + cmdString
const id = 1
- const action = commands.executeSingleCommand(cmd, id)
+ const action = commands.executeSingleCommand(cmd, { id })
const cmdChar = store.getState().settings.cmdchar
bus.take('NOOP', currentAction => {
@@ -441,7 +463,7 @@ describe('commandsDuck', () => {
const serverCmd = 'disconnect'
const cmd = store.getState().settings.cmdchar + 'server ' + serverCmd
const id = 3
- const action = commands.executeSingleCommand(cmd, id)
+ const action = commands.executeSingleCommand(cmd, { id })
bus.take('NOOP', currentAction => {
// Then
expect(store.getActions()).toEqual([
diff --git a/src/shared/modules/commands/cypher.test.js b/src/shared/modules/commands/cypher.test.js
index 2cfe9c544a7..d027f8d0093 100644
--- a/src/shared/modules/commands/cypher.test.js
+++ b/src/shared/modules/commands/cypher.test.js
@@ -76,7 +76,10 @@ describe('tx metadata with cypher', () => {
const bus = createBus()
bus.applyReduxMiddleware(createEpicMiddleware(handleSingleCommandEpic))
const $$responseChannel = 'test-channel'
- const action = executeSingleCommand('RETURN 1', 'id', 'rqid')
+ const action = executeSingleCommand('RETURN 1', {
+ id: 'id',
+ requestId: 'rqid'
+ })
action.$$responseChannel = $$responseChannel
bus.send(action.type, action)
diff --git a/src/shared/modules/commands/helpers/cypher.js b/src/shared/modules/commands/helpers/cypher.js
index 6dcf8d33551..bd7261942f7 100644
--- a/src/shared/modules/commands/helpers/cypher.js
+++ b/src/shared/modules/commands/helpers/cypher.js
@@ -42,7 +42,8 @@ export const handleCypherCommand = (
requestId: action.requestId,
cancelable: true,
...txMetadata,
- autoCommit
+ autoCommit,
+ useDb: action.useDb
}
)
put(send('cypher', id))
diff --git a/src/shared/modules/commands/multiCommands.test.js b/src/shared/modules/commands/multiCommands.test.js
index ebaa5b7a8da..7fc77a0b535 100644
--- a/src/shared/modules/commands/multiCommands.test.js
+++ b/src/shared/modules/commands/multiCommands.test.js
@@ -69,14 +69,14 @@ describe('handleCommandEpic', () => {
const cmd = 'RETURN 1'
const id = 2
const requestId = 'xxx'
- const action = commands.executeCommand(cmd, id, requestId)
+ const action = commands.executeCommand(cmd, { id, requestId })
bus.take('NOOP', currentAction => {
// Then
expect(store.getActions()).toEqual([
action,
commands.clearErrorMessage(),
addHistory(action.cmd, maxHistory),
- commands.executeSingleCommand(cmd, id, requestId),
+ commands.executeSingleCommand(cmd, { id, requestId }),
{ type: 'NOOP' }
])
done()
@@ -94,7 +94,11 @@ describe('handleCommandEpic', () => {
const id = 2
const requestId = 'xxx'
const parentId = 'yyy'
- const action = commands.executeCommand(cmd, id, requestId, parentId)
+ const action = commands.executeCommand(cmd, {
+ id,
+ requestId,
+ parentId
+ })
bus.take('NOOP', currentAction => {
// Then
diff --git a/src/shared/modules/commands/use-db-no-ww.test.js b/src/shared/modules/commands/use-db-no-ww.test.js
new file mode 100644
index 00000000000..5853f8949fc
--- /dev/null
+++ b/src/shared/modules/commands/use-db-no-ww.test.js
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2002-2020 "Neo4j,"
+ * Neo4j Sweden AB [http://neo4j.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+import { createEpicMiddleware } from 'redux-observable'
+import { createBus } from 'suber'
+import { flushPromises } from 'services/utils'
+import { executeSingleCommand, handleSingleCommandEpic } from './commandsDuck'
+import bolt from 'services/bolt/bolt'
+
+jest.mock('services/bolt/boltConnection', () => {
+ const orig = require.requireActual('services/bolt/boltConnection')
+ return {
+ ...orig,
+ routedWriteTransaction: jest.fn(() => [
+ 'id',
+ Promise.resolve({ records: [] })
+ ])
+ }
+})
+const boltConnection = require.requireMock('services/bolt/boltConnection')
+
+jest.mock('shared/modules/settings/settingsDuck', () => {
+ const orig = require.requireActual('shared/modules/settings/settingsDuck')
+ return {
+ ...orig,
+ getCmdChar: () => ':',
+ shouldUseCypherThread: () => false
+ }
+})
+const settingsDuck = require.requireMock('shared/modules/settings/settingsDuck')
+
+jest.mock('shared/modules/params/paramsDuck', () => {
+ const orig = require.requireActual('shared/modules/params/paramsDuck')
+ return {
+ ...orig,
+ getParams: () => ({})
+ }
+})
+
+jest.mock('shared/modules/dbMeta/dbMetaDuck', () => {
+ const orig = require.requireActual('shared/modules/dbMeta/dbMetaDuck')
+ return {
+ ...orig,
+ getVersion: () => '4.0.0'
+ }
+})
+
+describe('Specified target database', () => {
+ test('it uses the db in store if no specific db specified with the action', done => {
+ // Given
+ bolt.useDb('autoDb') // Fake setting the db
+ boltConnection.routedWriteTransaction.mockClear()
+
+ const bus = createBus()
+ bus.applyReduxMiddleware(createEpicMiddleware(handleSingleCommandEpic))
+ const $$responseChannel = 'test-channel'
+ const action = executeSingleCommand(`RETURN 1`)
+ action.$$responseChannel = $$responseChannel
+
+ bus.send(action.type, action)
+ flushPromises().then(() => {
+ expect(boltConnection.routedWriteTransaction).toHaveBeenCalledTimes(1)
+ expect(boltConnection.routedWriteTransaction).toHaveBeenCalledWith(
+ 'RETURN 1',
+ {},
+ expect.objectContaining({ useDb: 'autoDb' })
+ )
+
+ done()
+ })
+ })
+ test('it uses the specified db if passed in with the action', done => {
+ // Given
+ bolt.useDb('autoDb') // Fake setting the db
+ boltConnection.routedWriteTransaction.mockClear()
+
+ const bus = createBus()
+ bus.applyReduxMiddleware(createEpicMiddleware(handleSingleCommandEpic))
+ const $$responseChannel = 'test-channel'
+ const action = executeSingleCommand(`RETURN 1`, { useDb: 'manualDb' }) // <-- specify db
+ action.$$responseChannel = $$responseChannel
+
+ bus.send(action.type, action)
+ flushPromises().then(() => {
+ expect(boltConnection.routedWriteTransaction).toHaveBeenCalledTimes(1)
+ expect(boltConnection.routedWriteTransaction).toHaveBeenCalledWith(
+ 'RETURN 1',
+ {},
+ expect.objectContaining({ useDb: 'manualDb' })
+ )
+
+ done()
+ })
+ })
+})
diff --git a/src/shared/modules/commands/use-db-ww.test.js b/src/shared/modules/commands/use-db-ww.test.js
new file mode 100644
index 00000000000..99acc82e44a
--- /dev/null
+++ b/src/shared/modules/commands/use-db-ww.test.js
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2002-2020 "Neo4j,"
+ * Neo4j Sweden AB [http://neo4j.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+import { createEpicMiddleware } from 'redux-observable'
+import { createBus } from 'suber'
+import { flushPromises } from 'services/utils'
+import { executeSingleCommand, handleSingleCommandEpic } from './commandsDuck'
+import bolt from 'services/bolt/bolt'
+
+jest.mock('services/bolt/setup-bolt-worker', () => {
+ const orig = require.requireActual('services/bolt/setup-bolt-worker')
+ return {
+ ...orig,
+ setupBoltWorker: jest.fn(() => Promise.resolve({ records: [] }))
+ }
+})
+const setupWorkerModule = require.requireMock('services/bolt/setup-bolt-worker')
+
+jest.mock('shared/modules/settings/settingsDuck', () => {
+ const orig = require.requireActual('shared/modules/settings/settingsDuck')
+ return {
+ ...orig,
+ getCmdChar: () => ':',
+ shouldUseCypherThread: () => true
+ }
+})
+
+jest.mock('shared/modules/params/paramsDuck', () => {
+ const orig = require.requireActual('shared/modules/params/paramsDuck')
+ return {
+ ...orig,
+ getParams: () => ({})
+ }
+})
+
+jest.mock('shared/modules/dbMeta/dbMetaDuck', () => {
+ const orig = require.requireActual('shared/modules/dbMeta/dbMetaDuck')
+ return {
+ ...orig,
+ getVersion: () => '4.0.0'
+ }
+})
+
+describe('Specified target database, using web workers', () => {
+ beforeAll(() => {
+ // Fake window worker object
+ window.Worker = true
+ bolt.useDb('autoDb') // Fake setting the db
+ })
+ test('it uses the db in store if no specific db specified with the action', done => {
+ // Given
+ setupWorkerModule.setupBoltWorker.mockClear()
+ const bus = createBus()
+ bus.applyReduxMiddleware(createEpicMiddleware(handleSingleCommandEpic))
+ const $$responseChannel = 'test-channel'
+ const action = executeSingleCommand(`RETURN 1`)
+ action.$$responseChannel = $$responseChannel
+
+ bus.send(action.type, action)
+ flushPromises().then(() => {
+ expect(setupWorkerModule.setupBoltWorker).toHaveBeenCalledTimes(1)
+ expect(setupWorkerModule.setupBoltWorker).toHaveBeenCalledWith(
+ expect.anything(),
+ expect.anything(),
+ expect.objectContaining({
+ connectionProperties: expect.objectContaining({ useDb: 'autoDb' })
+ }),
+ expect.anything()
+ )
+
+ done()
+ })
+ })
+ test('it uses the specified db if passed in with the action', done => {
+ // Given
+ setupWorkerModule.setupBoltWorker.mockClear()
+ const bus = createBus()
+ bus.applyReduxMiddleware(createEpicMiddleware(handleSingleCommandEpic))
+ const $$responseChannel = 'test-channel'
+ const action = executeSingleCommand(`RETURN 1`, { useDb: 'manualDb' }) // <-- specify db
+ action.$$responseChannel = $$responseChannel
+
+ bus.send(action.type, action)
+ flushPromises().then(() => {
+ expect(setupWorkerModule.setupBoltWorker).toHaveBeenCalledTimes(1)
+ expect(setupWorkerModule.setupBoltWorker).toHaveBeenCalledWith(
+ expect.anything(),
+ expect.anything(),
+ expect.objectContaining({
+ connectionProperties: expect.objectContaining({ useDb: 'manualDb' })
+ }),
+ expect.anything()
+ )
+
+ done()
+ })
+ })
+})
diff --git a/src/shared/services/bolt/bolt.js b/src/shared/services/bolt/bolt.js
index 0bddaeeabca..27c2a29504a 100644
--- a/src/shared/services/bolt/bolt.js
+++ b/src/shared/services/bolt/bolt.js
@@ -27,13 +27,11 @@ import { generateBoltHost } from 'services/utils'
import {
runCypherMessage,
cancelTransactionMessage,
- closeConnectionMessage,
- CYPHER_ERROR_MESSAGE,
- CYPHER_RESPONSE_MESSAGE,
- POST_CANCEL_TRANSACTION_MESSAGE,
- BOLT_CONNECTION_ERROR_MESSAGE
+ closeConnectionMessage
} from './boltWorkerMessages'
import { NATIVE } from 'services/bolt/boltHelpers'
+import { setupBoltWorker, addTypesAsField } from './setup-bolt-worker'
+
import BoltWorkerModule from 'worker-loader?inline!./boltWorker.js'
let connectionProperties = null
@@ -78,7 +76,8 @@ function routedWriteTransaction(input, parameters, requestMetaData = {}) {
cancelable = false,
onLostConnection = () => {},
txMetadata = undefined,
- autoCommit = false
+ autoCommit = false,
+ useDb = null
} = requestMetaData
if (useCypherThread && window.Worker) {
const id = requestId || v4()
@@ -96,22 +95,25 @@ function routedWriteTransaction(input, parameters, requestMetaData = {}) {
)
),
txMetadata,
- useDb: _useDb,
+ useDb: useDb || _useDb,
autoCommit
}
)
- const workerPromise = setupBoltWorker(id, workFn, onLostConnection)
+ const workerPromise = setupBoltWorker(
+ boltWorkPool,
+ id,
+ workFn,
+ onLostConnection
+ )
return [id, workerPromise]
} else {
- return boltConnection.routedWriteTransaction(
- input,
- parameters,
+ return boltConnection.routedWriteTransaction(input, parameters, {
requestId,
cancelable,
txMetadata,
- _useDb,
+ useDb: useDb || _useDb,
autoCommit
- )
+ })
}
}
@@ -121,7 +123,8 @@ function routedReadTransaction(input, parameters, requestMetaData = {}) {
requestId = null,
cancelable = false,
onLostConnection = () => {},
- txMetadata = undefined
+ txMetadata = undefined,
+ useDb = null
} = requestMetaData
if (useCypherThread && window.Worker) {
const id = requestId || v4()
@@ -139,20 +142,23 @@ function routedReadTransaction(input, parameters, requestMetaData = {}) {
)
),
txMetadata,
- useDb: _useDb
+ useDb: useDb || _useDb
}
)
- const workerPromise = setupBoltWorker(id, workFn, onLostConnection)
+ const workerPromise = setupBoltWorker(
+ boltWorkPool,
+ id,
+ workFn,
+ onLostConnection
+ )
return workerPromise
} else {
- return boltConnection.routedReadTransaction(
- input,
- parameters,
+ return boltConnection.routedReadTransaction(input, parameters, {
requestId,
cancelable,
txMetadata,
- _useDb
- )
+ useDb: useDb || _useDb
+ })
}
}
@@ -163,7 +169,7 @@ function directTransaction(input, parameters, requestMetaData = {}) {
cancelable = false,
onLostConnection = () => {},
txMetadata = undefined,
- useDb
+ useDb = null
} = requestMetaData
if (useCypherThread && window.Worker) {
const id = requestId || v4()
@@ -181,63 +187,24 @@ function directTransaction(input, parameters, requestMetaData = {}) {
)
),
txMetadata,
- useDb: useDb !== undefined ? useDb : _useDb
+ useDb: useDb || _useDb
}
)
- const workerPromise = setupBoltWorker(id, workFn, onLostConnection)
+ const workerPromise = setupBoltWorker(
+ boltWorkPool,
+ id,
+ workFn,
+ onLostConnection
+ )
return workerPromise
} else {
- return boltConnection.directTransaction(
- input,
- parameters,
+ return boltConnection.directTransaction(input, parameters, {
requestId,
cancelable,
txMetadata,
- _useDb
- )
- }
-}
-
-const addTypesAsField = result => {
- const records = result.records.map(record => {
- const typedRecord = new neo4j.types.Record(
- record.keys,
- record._fields,
- record._fieldLookup
- )
- if (typedRecord._fields) {
- typedRecord._fields = mappings.applyGraphTypes(typedRecord._fields)
- }
- return typedRecord
- })
- const summary = mappings.applyGraphTypes(result.summary)
- return { summary, records }
-}
-
-function setupBoltWorker(id, workFn, onLostConnection = () => {}) {
- const workerPromise = new Promise((resolve, reject) => {
- const work = boltWorkPool.doWork({
- id,
- payload: workFn,
- onmessage: msg => {
- if (msg.data.type === BOLT_CONNECTION_ERROR_MESSAGE) {
- work.finish()
- onLostConnection(msg.data.error)
- return reject(msg.data.error)
- }
- if (msg.data.type === CYPHER_ERROR_MESSAGE) {
- work.finish()
- reject(msg.data.error)
- } else if (msg.data.type === CYPHER_RESPONSE_MESSAGE) {
- work.finish()
- resolve(addTypesAsField(msg.data.result))
- } else if (msg.data.type === POST_CANCEL_TRANSACTION_MESSAGE) {
- work.finish()
- }
- }
+ useDb: useDb || _useDb
})
- })
- return workerPromise
+ }
}
const closeConnectionInWorkers = () => {
diff --git a/src/shared/services/bolt/boltConnection.js b/src/shared/services/bolt/boltConnection.js
index 9d315c6bce9..c75693c032e 100644
--- a/src/shared/services/bolt/boltConnection.js
+++ b/src/shared/services/bolt/boltConnection.js
@@ -289,14 +289,13 @@ export function cancelTransaction(id, cb) {
}
}
-export function directTransaction(
- input,
- parameters,
- requestId = null,
- cancelable = false,
- txMetadata = undefined,
- useDb = undefined
-) {
+export function directTransaction(input, parameters, opts = {}) {
+ const {
+ requestId = null,
+ cancelable = false,
+ txMetadata = undefined,
+ useDb = undefined
+ } = opts
const session = _drivers
? _drivers
.getDirectDriver()
@@ -306,14 +305,13 @@ export function directTransaction(
return _trackedTransaction(input, parameters, session, requestId, txMetadata)
}
-export function routedReadTransaction(
- input,
- parameters,
- requestId = null,
- cancelable = false,
- txMetadata = undefined,
- useDb = undefined
-) {
+export function routedReadTransaction(input, parameters, opts = {}) {
+ const {
+ requestId = null,
+ cancelable = false,
+ txMetadata = undefined,
+ useDb = undefined
+ } = opts
const session = _drivers
? _drivers
.getRoutedDriver()
@@ -323,15 +321,14 @@ export function routedReadTransaction(
return _trackedTransaction(input, parameters, session, requestId, txMetadata)
}
-export function routedWriteTransaction(
- input,
- parameters,
- requestId = null,
- cancelable = false,
- txMetadata = undefined,
- useDb = undefined,
- autoCommit = false
-) {
+export function routedWriteTransaction(input, parameters, opts = {}) {
+ const {
+ requestId = null,
+ cancelable = false,
+ txMetadata = undefined,
+ useDb = undefined,
+ autoCommit = false
+ } = opts
const session = _drivers
? _drivers
.getRoutedDriver()
diff --git a/src/shared/services/bolt/boltWorker.js b/src/shared/services/bolt/boltWorker.js
index 5d4bd8e9a63..1af26f054f0 100644
--- a/src/shared/services/bolt/boltWorker.js
+++ b/src/shared/services/bolt/boltWorker.js
@@ -80,11 +80,7 @@ const onmessage = function(message) {
const res = connectionTypeMap[connectionType].create(
input,
applyGraphTypes(parameters),
- requestId,
- cancelable,
- txMetadata,
- useDb,
- autoCommit
+ { requestId, cancelable, txMetadata, useDb, autoCommit }
)
connectionTypeMap[connectionType]
.getPromise(res)
diff --git a/src/shared/services/bolt/setup-bolt-worker.js b/src/shared/services/bolt/setup-bolt-worker.js
new file mode 100644
index 00000000000..ea5e825ad81
--- /dev/null
+++ b/src/shared/services/bolt/setup-bolt-worker.js
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2002-2020 "Neo4j,"
+ * Neo4j Sweden AB [http://neo4j.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+import { types } from 'neo4j-driver'
+import { applyGraphTypes } from './boltMappings'
+import {
+ CYPHER_ERROR_MESSAGE,
+ CYPHER_RESPONSE_MESSAGE,
+ POST_CANCEL_TRANSACTION_MESSAGE,
+ BOLT_CONNECTION_ERROR_MESSAGE
+} from './boltWorkerMessages'
+
+export const setupBoltWorker = (
+ boltWorkPool,
+ id,
+ workFn,
+ onLostConnection = () => {}
+) => {
+ const workerPromise = new Promise((resolve, reject) => {
+ const work = boltWorkPool.doWork({
+ id,
+ payload: workFn,
+ onmessage: msg => {
+ if (msg.data.type === BOLT_CONNECTION_ERROR_MESSAGE) {
+ work.finish()
+ onLostConnection(msg.data.error)
+ return reject(msg.data.error)
+ }
+ if (msg.data.type === CYPHER_ERROR_MESSAGE) {
+ work.finish()
+ reject(msg.data.error)
+ } else if (msg.data.type === CYPHER_RESPONSE_MESSAGE) {
+ work.finish()
+ resolve(addTypesAsField(msg.data.result))
+ } else if (msg.data.type === POST_CANCEL_TRANSACTION_MESSAGE) {
+ work.finish()
+ }
+ }
+ })
+ })
+ return workerPromise
+}
+
+export const addTypesAsField = result => {
+ const records = result.records.map(record => {
+ const typedRecord = new types.Record(
+ record.keys,
+ record._fields,
+ record._fieldLookup
+ )
+ if (typedRecord._fields) {
+ typedRecord._fields = applyGraphTypes(typedRecord._fields)
+ }
+ return typedRecord
+ })
+ const summary = applyGraphTypes(result.summary)
+ return { summary, records }
+}
diff --git a/src/shared/services/commandInterpreterHelper.js b/src/shared/services/commandInterpreterHelper.js
index 64dffb51ce6..477bbac9c13 100644
--- a/src/shared/services/commandInterpreterHelper.js
+++ b/src/shared/services/commandInterpreterHelper.js
@@ -377,8 +377,8 @@ const availableCommands = [
put(cypher(action.cmd))
put(
frames.add({
- useDb: getUseDb(store.getState()),
...action,
+ useDb: action.useDb || getUseDb(store.getState()),
type: 'cypher',
requestId: id
})
diff --git a/src/shared/services/commandUtils.js b/src/shared/services/commandUtils.js
index 233a90dfa1e..b419d070c57 100644
--- a/src/shared/services/commandUtils.js
+++ b/src/shared/services/commandUtils.js
@@ -63,7 +63,7 @@ export const buildCommandObject = (action, interpret, cmdchar) => {
cmdchar,
action.ignore
)
- return { action, interpreted, cmdchar }
+ return { action, interpreted, cmdchar, useDb: action.useDb }
}
export const getInterpreter = (interpret, cmd, cmdchar, ignore = false) => {