Skip to content

Commit db03c77

Browse files
authored
[wbVWvi0y] Solves apoc.meta.data bug with reserved names for relationships and nodes (#3999)
1 parent fac7fb2 commit db03c77

File tree

2 files changed

+54
-21
lines changed

2 files changed

+54
-21
lines changed

core/src/main/java/apoc/meta/Meta.java

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,30 @@
9494
import org.neo4j.values.storable.DurationValue;
9595

9696
public class Meta {
97+
private class MetadataKey {
98+
Types type;
99+
String key;
100+
101+
MetadataKey(Types type, String key) {
102+
this.type = type;
103+
this.key = key;
104+
}
105+
106+
@Override
107+
public boolean equals(Object obj) {
108+
if (obj instanceof MetadataKey) {
109+
MetadataKey other = ((MetadataKey) obj);
110+
return other.type.equals(this.type) && other.key.equals(this.key);
111+
}
112+
113+
return false;
114+
}
115+
116+
@Override
117+
public int hashCode() {
118+
return (type.toString() + "-" + key).hashCode();
119+
}
120+
}
97121

98122
@Context
99123
public Transaction tx;
@@ -685,7 +709,7 @@ public Stream<MetaResult> data(@Name(value = "config", defaultValue = "{}") Map<
685709
public Stream<MapResult> schema(@Name(value = "config", defaultValue = "{}") Map<String, Object> config) {
686710
MetaStats metaStats = collectStats();
687711
SampleMetaConfig metaConfig = new SampleMetaConfig(config);
688-
Map<Set<String>, Map<String, MetaItem>> metaData =
712+
Map<MetadataKey, Map<String, MetaItem>> metaData =
689713
collectMetaData(new DatabaseSubGraph(transaction), metaConfig);
690714

691715
Map<String, Object> relationships = collectRelationshipsMetaData(metaStats, metaData);
@@ -824,23 +848,27 @@ private Tables4LabelsProfile collectTables4LabelsProfile(MetaConfig config) {
824848
}
825849

826850
// End new code
827-
828-
private Map<Set<String>, Map<String, MetaItem>> collectMetaData(SubGraph graph, SampleMetaConfig config) {
829-
Map<Set<String>, Map<String, MetaItem>> metaData = new LinkedHashMap<>(100);
851+
/**
852+
* Collects metadata for generating a metadata map based on the provided subgraph and configuration. This method iterates
853+
* over the labels and relationships in the subgraph, collects various metadata information, and stores it in the
854+
* metadata map.
855+
*/
856+
private Map<MetadataKey, Map<String, MetaItem>> collectMetaData(SubGraph graph, SampleMetaConfig config) {
857+
Map<MetadataKey, Map<String, MetaItem>> metaData = new LinkedHashMap<>(100);
830858

831859
Set<RelationshipType> types = Iterables.asSet(graph.getAllRelationshipTypesInUse());
832860
Map<String, Iterable<ConstraintDefinition>> relConstraints = new HashMap<>(20);
833861
Map<String, Set<String>> relIndexes = new HashMap<>();
834862
for (RelationshipType type : graph.getAllRelationshipTypesInUse()) {
835-
metaData.put(Set.of(Types.RELATIONSHIP.name(), type.name()), new LinkedHashMap<>(10));
863+
metaData.put(new MetadataKey(Types.RELATIONSHIP, type.name()), new LinkedHashMap<>(10));
836864
relConstraints.put(type.name(), graph.getConstraints(type));
837865
relIndexes.put(type.name(), getIndexedProperties(graph.getIndexes(type)));
838866
}
839867
for (Label label : graph.getAllLabelsInUse()) {
840868
Map<String, MetaItem> nodeMeta = new LinkedHashMap<>(50);
841869
String labelName = label.name();
842870
// workaround in case of duplicated keys
843-
metaData.put(Set.of(Types.NODE.name(), labelName), nodeMeta);
871+
metaData.put(new MetadataKey(Types.NODE, labelName), nodeMeta);
844872
Iterable<ConstraintDefinition> constraints = graph.getConstraints(label);
845873
Set<String> indexed = getIndexedProperties(graph.getIndexes(label));
846874
long labelCount = graph.countsForNode(label);
@@ -889,15 +917,15 @@ public static long getSampleForLabelCount(long labelCount, long sample) {
889917
}
890918

891919
private Map<String, Object> collectNodesMetaData(
892-
MetaStats metaStats, Map<Set<String>, Map<String, MetaItem>> metaData, Map<String, Object> relationships) {
920+
MetaStats metaStats, Map<MetadataKey, Map<String, MetaItem>> metaData, Map<String, Object> relationships) {
893921
Map<String, Object> nodes = new LinkedHashMap<>();
894922
Map<String, List<Map<String, Object>>> startNodeNameToRelationshipsMap = new HashMap<>();
895-
for (Set<String> metadataKey : metaData.keySet()) {
923+
for (MetadataKey metadataKey : metaData.keySet()) {
896924
Map<String, MetaItem> entityData = metaData.get(metadataKey);
897925
Map<String, Object> entityProperties = new LinkedHashMap<>();
898926
Map<String, Object> entityRelationships = new LinkedHashMap<>();
899927
List<String> labels = new LinkedList<>();
900-
boolean isNode = metaStats.labels.keySet().stream().anyMatch(metadataKey::contains);
928+
boolean isNode = metaStats.labels.keySet().stream().anyMatch((label) -> metadataKey.key.equals(label));
901929
for (String entityDataKey : entityData.keySet()) {
902930
MetaItem metaItem = entityData.get(entityDataKey);
903931
if (metaItem.elementType.equals("relationship")) {
@@ -958,7 +986,7 @@ private Map<String, Object> collectNodesMetaData(
958986
}
959987
}
960988
if (isNode) {
961-
String key = getKeyFromEntityName(metadataKey, Types.NODE.name());
989+
String key = metadataKey.key;
962990
nodes.put(
963991
key,
964992
MapUtil.map(
@@ -999,12 +1027,13 @@ private void setIncomingRelationships(
9991027
}
10001028

10011029
private Map<String, Object> collectRelationshipsMetaData(
1002-
MetaStats metaStats, Map<Set<String>, Map<String, MetaItem>> metaData) {
1030+
MetaStats metaStats, Map<MetadataKey, Map<String, MetaItem>> metaData) {
10031031
Map<String, Object> relationships = new LinkedHashMap<>();
1004-
for (Set<String> metadataKey : metaData.keySet()) {
1032+
for (MetadataKey metadataKey : metaData.keySet()) {
10051033
Map<String, MetaItem> entityData = metaData.get(metadataKey);
10061034
Map<String, Object> entityProperties = new LinkedHashMap<>();
1007-
boolean isRelationship = metaStats.relTypesCount.keySet().stream().anyMatch(metadataKey::contains);
1035+
boolean isRelationship =
1036+
metaStats.relTypesCount.keySet().stream().anyMatch((rel) -> metadataKey.key.equals(rel));
10081037
for (String entityDataKey : entityData.keySet()) {
10091038
MetaItem metaItem = entityData.get(entityDataKey);
10101039
if (!metaItem.elementType.equals("relationship")) {
@@ -1022,7 +1051,7 @@ private Map<String, Object> collectRelationshipsMetaData(
10221051
}
10231052
}
10241053
if (isRelationship) {
1025-
String key = getKeyFromEntityName(metadataKey, Types.RELATIONSHIP.name());
1054+
String key = metadataKey.key;
10261055
relationships.put(
10271056
key,
10281057
MapUtil.map(
@@ -1037,11 +1066,6 @@ private Map<String, Object> collectRelationshipsMetaData(
10371066
return relationships;
10381067
}
10391068

1040-
private String getKeyFromEntityName(Set<String> entityName, String suffix) {
1041-
return new HashSet<>(entityName)
1042-
.stream().filter(entity -> !entity.equals(suffix)).findFirst().get();
1043-
}
1044-
10451069
private void addProperties(
10461070
Map<String, MetaItem> properties,
10471071
String labelName,
@@ -1059,7 +1083,7 @@ private void addProperties(
10591083
}
10601084

10611085
private void addRelationships(
1062-
Map<Set<String>, Map<String, MetaItem>> metaData,
1086+
Map<MetadataKey, Map<String, MetaItem>> metaData,
10631087
Map<String, MetaItem> nodeMeta,
10641088
String labelName,
10651089
Node node,
@@ -1079,7 +1103,7 @@ private void addRelationships(
10791103
if (!nodeMeta.containsKey(typeName)) nodeMeta.put(typeName, new MetaItem(labelName, typeName));
10801104
int in = node.getDegree(type, Direction.INCOMING);
10811105

1082-
Map<String, MetaItem> typeMeta = metaData.get(Set.of(typeName, Types.RELATIONSHIP.name()));
1106+
Map<String, MetaItem> typeMeta = metaData.get(new MetadataKey(Types.RELATIONSHIP, typeName));
10831107
if (!typeMeta.containsKey(labelName)) typeMeta.put(labelName, new MetaItem(typeName, labelName));
10841108
MetaItem relMeta = nodeMeta.get(typeName);
10851109
addOtherNodeInfo(node, labelName, out, in, type, relMeta, typeMeta, constraints, indexes);

core/src/test/java/apoc/meta/MetaTest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,15 @@ public void testMetaDataWithSampleNormalized() throws Exception {
983983
});
984984
}
985985

986+
@Test
987+
public void testRelationshipAndNodeNames() {
988+
db.executeTransactionally("CREATE (a:NODE)-[r:RELATIONSHIP]->(m:Movie)");
989+
TestUtil.testResult(db, "CALL apoc.meta.data()", (r) -> {
990+
Assertions.assertThat(r.stream().map(m -> m.get("label"))).contains("RELATIONSHIP", "NODE");
991+
r.close();
992+
});
993+
}
994+
986995
@Test
987996
public void testMetaDataWithSample5() throws Exception {
988997
db.executeTransactionally("create index on :Person(name)");

0 commit comments

Comments
 (0)