Skip to content

Commit d0e14d5

Browse files
committed
Fix virtual node id working (#743)
1 parent 02317e8 commit d0e14d5

File tree

2 files changed

+62
-4
lines changed

2 files changed

+62
-4
lines changed

common/src/main/java/apoc/result/VirtualNode.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public VirtualNode(Label[] labels, Map<String, Object> props) {
4747
this.id = MIN_ID.decrementAndGet();
4848
addLabels(asList(labels));
4949
this.props.putAll(props);
50-
this.elementId = null;
50+
this.elementId = UUID.randomUUID().toString();
5151
}
5252

5353
@SuppressWarnings("unused") // used from extended
@@ -67,13 +67,14 @@ public VirtualNode(Node node, List<String> propertyNames, boolean wrapNodeIDs) {
6767
Objects.requireNonNull(node, ERROR_NODE_NULL);
6868
final long id = node.getId();
6969
// if node is already virtual, we return the same id
70-
this.id = id < 0 || wrapNodeIDs ? id : -id - 1;
70+
this.id = id < 0 || wrapNodeIDs ? id : MIN_ID.decrementAndGet();
71+
this.elementId = id < 0 || wrapNodeIDs
72+
? node.getElementId()
73+
: UUID.randomUUID().toString();
7174
// to not overlap this nodes ids with ids from VirtualNode(Label[] labels, Map<String, Object> props)
72-
MIN_ID.updateAndGet(x -> Math.min(x, this.id));
7375
this.labels.addAll(Util.labelStrings(node));
7476
String[] keys = propertyNames.toArray(new String[propertyNames.size()]);
7577
this.props.putAll(node.getProperties(keys));
76-
this.elementId = node.getElementId();
7778
}
7879

7980
public VirtualNode(Node node, List<String> propertyNames) {

core/src/test/java/apoc/create/CreateTest.java

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import apoc.path.Paths;
3131
import apoc.util.TestUtil;
3232
import apoc.util.collection.Iterables;
33+
import java.util.HashSet;
3334
import java.util.Iterator;
3435
import java.util.List;
3536
import java.util.Map;
@@ -415,6 +416,62 @@ public void testVirtualFromNodeFunction() {
415416
});
416417
}
417418

419+
@Test
420+
public void test2VirtualFromNodesHaveUniqueIDs() {
421+
testCall(
422+
db,
423+
"""
424+
CREATE (n1:Cat { name:'Maja', born: 2023 } ), (n2:Cat { name:'Pelle', born: 2023 } )
425+
RETURN apoc.create.virtual.fromNode(n1, ['name']) AS node1, apoc.create.virtual.fromNode(n2, ['name']) AS node2
426+
""",
427+
(row) -> {
428+
Node node1 = (Node) row.get("node1");
429+
430+
assertTrue(node1.hasLabel(label("Cat")));
431+
var firstNodeID = node1.getId();
432+
assertTrue(node1.getId() < 0);
433+
assertEquals("Maja", node1.getProperty("name"));
434+
assertNull(node1.getProperty("born"));
435+
436+
Node node2 = (Node) row.get("node2");
437+
438+
assertTrue(node2.hasLabel(label("Cat")));
439+
var secondNodeID = node2.getId();
440+
assertTrue(node2.getId() < 0);
441+
assertEquals("Pelle", node2.getProperty("name"));
442+
assertNull(node2.getProperty("born"));
443+
444+
assertNotEquals(firstNodeID, secondNodeID);
445+
});
446+
}
447+
448+
@Test
449+
public void testVirtualFromSameNodesHaveUniqueIDs() {
450+
testResult(
451+
db,
452+
"""
453+
CREATE (n1:Cat { name:'Maja', born: 2023 } )
454+
WITH n1
455+
UNWIND [1,2,3] AS i
456+
RETURN apoc.create.virtual.fromNode(n1, ['name']) AS node1
457+
""",
458+
(result) -> {
459+
HashSet<Long> nodeIDs = new HashSet<>();
460+
while (result.hasNext()) {
461+
Map<String, Object> r = result.next();
462+
Node node1 = (Node) r.get("node1");
463+
464+
assertTrue(node1.hasLabel(label("Cat")));
465+
nodeIDs.add(node1.getId());
466+
assertTrue(node1.getId() < 0);
467+
assertEquals("Maja", node1.getProperty("name"));
468+
assertNull(node1.getProperty("born"));
469+
}
470+
471+
assertEquals(3, nodeIDs.size());
472+
});
473+
}
474+
418475
@Test
419476
public void testVirtualFromNodeFunctionWithWrapping() {
420477
testCall(

0 commit comments

Comments
 (0)