Skip to content
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

Migrate to using elementId #84

Merged
merged 3 commits into from
Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/
package com.albertoventurini.graphdbplugin.database.api;

import com.albertoventurini.graphdbplugin.database.api.data.GraphDatabaseVersion;
import com.albertoventurini.graphdbplugin.database.api.data.GraphMetadata;
import com.albertoventurini.graphdbplugin.database.api.query.GraphQueryResult;

Expand All @@ -18,4 +19,6 @@ public interface GraphDatabaseApi {
GraphQueryResult execute(String query, Map<String, Object> statementParameters);

GraphMetadata metadata();

GraphDatabaseVersion getVersion();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* Copied and adapted from plugin
* <a href="https://github.com/neueda/jetbrains-plugin-graph-database-support">Graph Database Support</a>
* by Neueda Technologies, Ltd.
* Modified by Alberto Venturini, 2022
*/
package com.albertoventurini.graphdbplugin.database.api.data;

public interface GraphDatabaseVersion {
String toString();

String idFunction();

Object idToParameter(String id);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
package com.albertoventurini.graphdbplugin.database.neo4j.bolt;

import com.albertoventurini.graphdbplugin.database.api.GraphDatabaseApi;
import com.albertoventurini.graphdbplugin.database.api.data.GraphDatabaseVersion;
import com.albertoventurini.graphdbplugin.database.api.data.GraphMetadata;
import com.albertoventurini.graphdbplugin.database.api.query.GraphQueryResult;
import com.albertoventurini.graphdbplugin.database.neo4j.bolt.data.Neo4jGraphDatabaseVersion;
import com.albertoventurini.graphdbplugin.database.neo4j.bolt.query.Neo4jBoltQueryResult;
import com.albertoventurini.graphdbplugin.database.neo4j.bolt.query.Neo4jBoltQueryResultRow;
import org.neo4j.driver.AuthToken;
import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Driver;
Expand All @@ -21,14 +24,21 @@
import org.neo4j.driver.exceptions.ClientException;

import java.nio.channels.UnresolvedAddressException;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.stream.IntStream;

/**
* Communicates with Neo4j 3.0+ database using Bolt driver.
*/
public class Neo4jBoltDatabase implements GraphDatabaseApi {

private static final String VERSION_QUERY = """
CALL dbms.components() YIELD versions
RETURN versions[0] AS version
""";

private final String url;
private final AuthToken auth;
private final SessionConfig dbConfig;
Expand Down Expand Up @@ -110,4 +120,19 @@ public GraphQueryResult execute(String query, Map<String, Object> statementParam
public GraphMetadata metadata() {
throw new IllegalStateException("Not implemented");
}

@Override
public GraphDatabaseVersion getVersion() {
var result = execute(VERSION_QUERY);
var row = result.getRows().get(0);
var neo4jRow = (Neo4jBoltQueryResultRow) row;
var rawVersion = neo4jRow.getValue("version").asString();
var parsedVersion = IntStream.concat(
Arrays.stream(rawVersion.split("\\.", 4))
.limit(3)
.mapToInt(Integer::parseInt),
IntStream.generate(() -> 0)
).limit(3).toArray();
return new Neo4jGraphDatabaseVersion(parsedVersion[0], parsedVersion[1], parsedVersion[2]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class Neo4jBoltNode implements GraphNode {
private final List<String> types;

public Neo4jBoltNode(Node value) {
this.id = String.valueOf(value.id());
this.id = String.valueOf(value.elementId());
this.types = Iterables.asList(value.labels());
this.propertyContainer = new Neo4jBoltPropertyContainer(value.asMap());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ public class Neo4jBoltRelationship implements GraphRelationship {
private GraphNode endNode;

public Neo4jBoltRelationship(Relationship rel) {
this.id = String.valueOf(rel.id());
this.id = String.valueOf(rel.elementId());
this.types = Collections.singletonList(rel.type());
this.propertyContainer = new Neo4jBoltPropertyContainer(rel.asMap());

this.startNodeId = String.valueOf(rel.startNodeId());
this.endNodeId = String.valueOf(rel.endNodeId());
this.startNodeId = String.valueOf(rel.startNodeElementId());
this.endNodeId = String.valueOf(rel.endNodeElementId());
}

public Neo4jBoltRelationship(String id, List<String> types, GraphPropertyContainer propertyContainer, String startNodeId, String endNodeId) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* Copied and adapted from plugin
* <a href="https://github.com/neueda/jetbrains-plugin-graph-database-support">Graph Database Support</a>
* by Neueda Technologies, Ltd.
* Modified by Alberto Venturini, 2022
*/
package com.albertoventurini.graphdbplugin.database.neo4j.bolt.data;

import com.albertoventurini.graphdbplugin.database.api.data.GraphDatabaseVersion;

public record Neo4jGraphDatabaseVersion(int major, int minor, int patch) implements GraphDatabaseVersion {

@Override
public String toString() {
return "Neo4j/" + major + "." + minor + "." + patch;
}

@Override
public String idFunction() {
if (major >= 5) {
return "elementId";
}
return "id";
}

@Override
public Object idToParameter(String id) {
if (major >= 5) {
return id;
}
return Long.parseLong(id);
}
}
2 changes: 2 additions & 0 deletions graph-database-plugin/src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@
serviceImplementation="com.albertoventurini.graphdbplugin.jetbrains.ui.datasource.DataSourcesView"/>
<projectService
serviceImplementation="com.albertoventurini.graphdbplugin.jetbrains.ui.console.params.ParametersService"/>
<projectService
serviceImplementation="com.albertoventurini.graphdbplugin.jetbrains.database.VersionService"/>

<scratch.rootType implementation="com.albertoventurini.graphdbplugin.jetbrains.ui.datasource.interactions.GraphDbEditorsConsoleRootType"/>
<scratch.rootType implementation="com.albertoventurini.graphdbplugin.jetbrains.ui.console.params.ParameterRootType"/>
Expand Down
1 change: 1 addition & 0 deletions platform/src/main/java/icons/GraphIcons.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public static final class Window {
}

public static final class Nodes {
public static final Icon VERSION = AllIcons.Actions.InlayGear;
public static final Icon INDEX = AllIcons.Nodes.ResourceBundle;
public static final Icon CONSTRAINT = AllIcons.Nodes.C_protected;
public static final Icon LABEL = AllIcons.Nodes.Class;
Expand Down
1 change: 1 addition & 0 deletions testing/integration-neo4j/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ dependencies {
testImplementation project(':graph-database-plugin')
testImplementation project(':ui:jetbrains')
testImplementation project(':language:cypher')
testImplementation project(':database:api')
testImplementation project(':database:neo4j')
testImplementation project(':testing:common')
testImplementation project(':platform')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,9 @@
package com.albertoventurini.graphdbplugin.test.integration.neo4j.tests.database.common;

import com.albertoventurini.graphdbplugin.jetbrains.component.datasource.metadata.DataSourceMetadata;
import com.albertoventurini.graphdbplugin.jetbrains.component.datasource.metadata.neo4j.Neo4jProcedureMetadata;
import com.albertoventurini.graphdbplugin.jetbrains.component.datasource.state.DataSourceApi;
import com.albertoventurini.graphdbplugin.test.integration.neo4j.util.base.BaseIntegrationTest;

import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
Expand All @@ -32,13 +30,13 @@ public void setUp() throws Exception {
public abstract DataSourceApi getDataSource();

public void testMetadataExists() throws ExecutionException, InterruptedException {
Optional<DataSourceMetadata> metadata = component().dataSourcesMetadata().getMetadata(getDataSource()).get();
Optional<DataSourceMetadata> metadata = component().dataSourcesMetadata().updateMetadata(getDataSource()).get();
assertThat(metadata).isPresent();
}

protected DataSourceMetadata getMetadata() {
try {
CompletableFuture<Optional<DataSourceMetadata>> futureMeta = component().dataSourcesMetadata().getMetadata(getDataSource());
CompletableFuture<Optional<DataSourceMetadata>> futureMeta = component().dataSourcesMetadata().updateMetadata(getDataSource());
return futureMeta.get(30, TimeUnit.SECONDS)
.orElseThrow(() -> new IllegalStateException("Metadata should not be null"));
} catch (InterruptedException | ExecutionException | TimeoutException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/
package com.albertoventurini.graphdbplugin.test.integration.neo4j.tests.database.neo4j;

import com.albertoventurini.graphdbplugin.database.neo4j.bolt.data.Neo4jGraphDatabaseVersion;
import com.albertoventurini.graphdbplugin.jetbrains.component.datasource.metadata.neo4j.Neo4jMetadata;
import com.albertoventurini.graphdbplugin.jetbrains.component.datasource.metadata.neo4j.Neo4jFunctionMetadata;
import com.albertoventurini.graphdbplugin.jetbrains.component.datasource.metadata.neo4j.Neo4jProcedureMetadata;
Expand Down Expand Up @@ -39,4 +40,11 @@ public void testMetadataHaveRequiredProcedures() {
&& p.signature().equals("db.labels() :: (label :: STRING?)")
&& p.description().equals("List all available labels in the database.")));
}

public void testGetVersion() {
var metadata = (Neo4jMetadata) getMetadata();
var version = (Neo4jGraphDatabaseVersion) metadata.version();
assertEquals(5, version.major());
assertEquals(2, version.minor());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,7 @@ public DataSourcesComponentState getState() {
}

public void refreshAllMetadata() {
getDataSourceContainer().getDataSources().forEach(d -> {
componentMetadata.getMetadata(d);
});
getDataSourceContainer().getDataSources().forEach(componentMetadata::updateMetadata);
}
//
// @NotNull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.albertoventurini.graphdbplugin.jetbrains.component.datasource.metadata.neo4j.Neo4jMetadataBuilder;
import com.albertoventurini.graphdbplugin.jetbrains.component.datasource.metadata.neo4j.Neo4jRelationshipTypeMetadata;
import com.albertoventurini.graphdbplugin.jetbrains.component.datasource.state.DataSourceApi;
import com.albertoventurini.graphdbplugin.jetbrains.database.VersionService;
import com.albertoventurini.graphdbplugin.jetbrains.services.ExecutorService;
import com.albertoventurini.graphdbplugin.jetbrains.ui.datasource.metadata.MetadataRetrieveEvent;
import com.intellij.openapi.application.ApplicationManager;
Expand All @@ -31,16 +32,18 @@ public class DataSourcesComponentMetadata {
private CypherMetadataProviderService cypherMetadataProviderService;
private ExecutorService executorService;
private MessageBus messageBus;
private VersionService versionService;

public DataSourcesComponentMetadata(final Project project) {
messageBus = project.getMessageBus();
cypherMetadataProviderService = project.getService(CypherMetadataProviderService.class);
executorService = ApplicationManager.getApplication().getService(ExecutorService.class);
versionService = project.getService(VersionService.class);

handlers.put(DataSourceType.NEO4J_BOLT, new Neo4jMetadataBuilder());
}

public CompletableFuture<Optional<DataSourceMetadata>> getMetadata(DataSourceApi dataSource) {
public CompletableFuture<Optional<DataSourceMetadata>> updateMetadata(DataSourceApi dataSource) {
MetadataRetrieveEvent metadataRetrieveEvent = messageBus.syncPublisher(MetadataRetrieveEvent.METADATA_RETRIEVE_EVENT);

metadataRetrieveEvent.startMetadataRefresh(dataSource);
Expand Down Expand Up @@ -84,5 +87,7 @@ private void updateNeo4jBoltMetadata(DataSourceApi dataSource, Neo4jMetadata met
metadata.propertyKeys().forEach(container::addPropertyKey);
metadata.procedures().forEach(p -> container.addProcedure(p.name(), p.signature(), p.description()));
metadata.functions().forEach(f -> container.addFunction(f.name(), f.signature(), f.description()));

versionService.updatedVersion(dataSource, metadata.version());
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.albertoventurini.graphdbplugin.jetbrains.component.datasource.metadata.neo4j;

import com.albertoventurini.graphdbplugin.database.api.data.GraphDatabaseVersion;
import com.albertoventurini.graphdbplugin.jetbrains.component.datasource.metadata.DataSourceMetadata;

import java.util.*;

public record Neo4jMetadata(
GraphDatabaseVersion version,
List<Neo4jFunctionMetadata> functions,
List<Neo4jProcedureMetadata> procedures,
List<Neo4jConstraintMetadata> constraints,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.albertoventurini.graphdbplugin.jetbrains.component.datasource.metadata.neo4j;

import com.albertoventurini.graphdbplugin.database.api.GraphDatabaseApi;
import com.albertoventurini.graphdbplugin.database.api.data.GraphDatabaseVersion;
import com.albertoventurini.graphdbplugin.database.neo4j.bolt.data.Neo4jGraphDatabaseVersion;
import com.albertoventurini.graphdbplugin.database.neo4j.bolt.query.Neo4jBoltQueryResultRow;
import com.albertoventurini.graphdbplugin.jetbrains.component.datasource.metadata.DataSourceMetadata;
import com.albertoventurini.graphdbplugin.jetbrains.component.datasource.metadata.MetadataBuilder;
Expand Down Expand Up @@ -50,6 +52,7 @@ public DataSourceMetadata buildMetadata(DataSourceApi dataSource) {
final var databaseManager = ApplicationManager.getApplication().getService(DatabaseManagerService.class);
final GraphDatabaseApi db = databaseManager.getDatabaseFor(dataSource);

GraphDatabaseVersion version = new Neo4jGraphDatabaseVersion(0, 0, 0);
final List<Neo4jIndexMetadata> indexes = new ArrayList<>();
final List<Neo4jProcedureMetadata> procedures = new ArrayList<>();
final List<Neo4jConstraintMetadata> constraints = new ArrayList<>();
Expand All @@ -60,15 +63,17 @@ public DataSourceMetadata buildMetadata(DataSourceApi dataSource) {
procedures.addAll(getProcedures(db));
constraints.addAll(getConstraints(db));
functions.addAll(getFunctions(db));
version = db.getVersion();
} catch (Exception e) {
LOG.warn("Unable to load indexes, constraints, procedures, or functions from the current database. Please upgrade to Neo4j 4.2+ to fix this.");
LOG.warn("Unable to load indexes, constraints, procedures, functions, or version from the current database. Please upgrade to Neo4j 4.2+ to fix this.");
}

final var propertyKeys = getPropertyKeys(db);
final var labels = getLabels(db);
final var relationshipTypes = getRelationshipTypes(db);

return new Neo4jMetadata(
version,
functions,
procedures,
constraints,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,36 +20,42 @@
public class DiffService {

private final QueryExecutionService service;
private final VersionService versionService;

public DiffService(Project project) {
this.service = new QueryExecutionService(project, project.getMessageBus());
service = new QueryExecutionService(project, project.getMessageBus());
versionService = project.getService(VersionService.class);
}

public void updateNode(DataSourceApi api, GraphEntity oldNode, GraphEntity newNode) {

String query = "MATCH (n) WHERE ID(n) = $id " +
diffLabels(oldNode.getTypes(), newNode.getTypes()) +
" SET n = $props" +
" RETURN n";
service.executeQuery(api, new ExecuteQueryPayload(query,
ImmutableMap.of(
"id", Long.parseLong(oldNode.getId()),
"props", newNode.getPropertyContainer().getProperties()),
null));
versionService.getVersion(api)
.thenAccept(version -> {
String query = "MATCH (n) WHERE " + version.idFunction() + "(n) = $id " +
diffLabels(oldNode.getTypes(), newNode.getTypes()) +
" SET n = $props" +
" RETURN n";
service.executeQuery(api, new ExecuteQueryPayload(query,
ImmutableMap.of(
"id", version.idToParameter(oldNode.getId()),
"props", newNode.getPropertyContainer().getProperties()),
null));
});
}


public void updateRelationShip(DataSourceApi api, GraphEntity relationship,
GraphEntity updatedRel) {

String query = "MATCH ()-[n]->() WHERE ID(n) = $id " +
" SET n = $props" +
" RETURN n";
service.executeQuery(api, new ExecuteQueryPayload(query,
ImmutableMap.of(
"id", Long.parseLong(relationship.getId()),
"props", updatedRel.getPropertyContainer().getProperties()),
null));
versionService.getVersion(api)
.thenAccept(version -> {
String query = "MATCH ()-[n]->() WHERE " + version.idFunction() + "(n) = $id " +
" SET n = $props" +
" RETURN n";
service.executeQuery(api, new ExecuteQueryPayload(query,
ImmutableMap.of(
"id", version.idToParameter(relationship.getId()),
"props", updatedRel.getPropertyContainer().getProperties()),
null));
});
}

public void saveNewNode(DataSourceApi api, GraphEntity newNode) {
Expand Down
Loading