diff --git a/e2e_tests/integration/multi-db.spec.js b/e2e_tests/integration/multi-db.spec.js
index 0902e53d14f..dc0fda213cb 100644
--- a/e2e_tests/integration/multi-db.spec.js
+++ b/e2e_tests/integration/multi-db.spec.js
@@ -27,10 +27,14 @@ describe('Multi database', () => {
cy.get('[data-testid="dbs-command-list"] li', {
timeout: 5000
})
- const databaseOptionList = () =>
+ const databaseOptionListOptions = () =>
cy.get('[data-testid="database-selection-list"] option', {
timeout: 5000
})
+ const databaseOptionList = () =>
+ cy.get('[data-testid="database-selection-list"]', {
+ timeout: 5000
+ })
before(() => {
cy.visit(Cypress.config('url'))
@@ -83,19 +87,48 @@ describe('Multi database', () => {
it('lists databases in sidebar', () => {
cy.executeCommand(':clear')
cy.get('[data-testid="drawerDBMS"]').click()
- databaseOptionList().should('have.length', 2)
+ databaseOptionListOptions().should('have.length', 2)
+ cy.get('[data-testid="drawerDBMS"]').click()
})
if (isEnterpriseEdition()) {
- it('lists new databases in sidebar', () => {
+ it('adds databases to the sidebar and adds backticks to special db names', () => {
+ // Add db
cy.executeCommand(':use system')
- cy.executeCommand('CREATE DATABASE sidebartest')
- databaseOptionList().should('have.length', 3)
- databaseOptionList().contains('system')
- databaseOptionList().contains('neo4j')
- databaseOptionList().contains('sidebartest')
+ cy.executeCommand('CREATE DATABASE `name-with-dash`')
+ cy.resultContains('1 system update')
+ cy.executeCommand(':clear')
- cy.executeCommand('DROP DATABASE sidebartest')
- databaseOptionList().should('have.length', 2)
+ // Count items in list
+ cy.get('[data-testid="drawerDBMS"]').click()
+ databaseOptionListOptions().should('have.length', 3)
+ databaseOptionListOptions().contains('system')
+ databaseOptionListOptions().contains('neo4j')
+ databaseOptionListOptions().contains('name-with-dash')
+
+ // Select to use db, make sure backticked
+ databaseOptionList().select('name-with-dash')
+ cy.get('[data-testid="frameCommand"]', { timeout: 10000 })
+ .first()
+ .should('contain', ':use `name-with-dash`')
+ cy.resultContains(
+ 'Queries from this point and forward are using the database'
+ )
+
+ // Try without backticks
+ cy.executeCommand(':use system')
+ cy.resultContains(
+ 'Queries from this point and forward are using the database'
+ )
+ cy.executeCommand(':clear')
+ cy.executeCommand(':use name-with-dash')
+ cy.resultContains(
+ 'Queries from this point and forward are using the database'
+ )
+
+ // Cleanup
+ cy.executeCommand(':use system')
+ cy.executeCommand('DROP DATABASE `name-with-dash`')
+ databaseOptionListOptions().should('have.length', 2)
cy.get('[data-testid="drawerDBMS"]').click()
})
}
diff --git a/src/browser/modules/DBMSInfo/DatabaseSelector.jsx b/src/browser/modules/DBMSInfo/DatabaseSelector.jsx
index 288b13829c8..711f6b2047c 100644
--- a/src/browser/modules/DBMSInfo/DatabaseSelector.jsx
+++ b/src/browser/modules/DBMSInfo/DatabaseSelector.jsx
@@ -26,6 +26,7 @@ import {
DrawerSectionBody
} from 'browser-components/drawer/index'
import { uniqBy } from 'lodash-es'
+import { escapeCypherIdentifier } from 'services/utils'
const Select = styled.select`
width: 100%;
@@ -47,7 +48,7 @@ export const DatabaseSelector = ({
if (target.value === EMPTY_OPTION) {
return
}
- onChange(target.value)
+ onChange(escapeCypherIdentifier(target.value))
}
let databasesList = databases
diff --git a/src/browser/modules/DBMSInfo/DatabaseSelector.test.jsx b/src/browser/modules/DBMSInfo/DatabaseSelector.test.jsx
index 40c80d70719..16ae0d65ae3 100644
--- a/src/browser/modules/DBMSInfo/DatabaseSelector.test.jsx
+++ b/src/browser/modules/DBMSInfo/DatabaseSelector.test.jsx
@@ -114,4 +114,32 @@ describe('DatabaseSelector', () => {
expect(onChange).toHaveBeenCalledTimes(2)
expect(onChange).toHaveBeenLastCalledWith('stella')
})
+ it('escapes db names when needed', () => {
+ // Given
+ const databases = [
+ { name: 'regulardb', status: 'online' },
+ { name: 'db-with-dash', status: 'online' }
+ ]
+ const onChange = jest.fn()
+
+ // When
+ const { getByTestId } = render(
+
There are no properties in database
if (properties.length > 0) { const editorCommandTemplate = text => { - return `MATCH (n) WHERE EXISTS(n.${ecsapeCypherMetaItem( + return `MATCH (n) WHERE EXISTS(n.${escapeCypherIdentifier( text - )}) RETURN DISTINCT "node" as entity, n.${ecsapeCypherMetaItem( + )}) RETURN DISTINCT "node" as entity, n.${escapeCypherIdentifier( text - )} AS ${ecsapeCypherMetaItem( + )} AS ${escapeCypherIdentifier( text - )} LIMIT 25 UNION ALL MATCH ()-[r]-() WHERE EXISTS(r.${ecsapeCypherMetaItem( + )} LIMIT 25 UNION ALL MATCH ()-[r]-() WHERE EXISTS(r.${escapeCypherIdentifier( text - )}) RETURN DISTINCT "relationship" AS entity, r.${ecsapeCypherMetaItem( + )}) RETURN DISTINCT "relationship" AS entity, r.${escapeCypherIdentifier( text - )} AS ${ecsapeCypherMetaItem(text)} LIMIT 25` + )} AS ${escapeCypherIdentifier(text)} LIMIT 25` } propertyItems = createItems( properties, diff --git a/src/browser/modules/Stream/Auth/DbsFrame.jsx b/src/browser/modules/Stream/Auth/DbsFrame.jsx index f7c157da287..3c50795295f 100644 --- a/src/browser/modules/Stream/Auth/DbsFrame.jsx +++ b/src/browser/modules/Stream/Auth/DbsFrame.jsx @@ -28,7 +28,7 @@ import { } from './styled' import { H3 } from 'browser-components/headers' import Render from 'browser-components/Render/index' -import { toKeyString } from 'services/utils' +import { toKeyString, escapeCypherIdentifier } from 'services/utils' import { UnstyledList } from '../styled' import { useDbCommand } from 'shared/modules/commands/commandsDuck' import TextCommand from 'browser/modules/DecoratedText/TextCommand' @@ -59,7 +59,11 @@ export const DbsFrame = props => { {dbsToShow.map(db => { return (