From 20d7afca7d1af1f8ec3aa544cccd0dabc0382e7f Mon Sep 17 00:00:00 2001 From: Stefano Azzalini Date: Sat, 27 Dec 2025 22:32:36 +0100 Subject: [PATCH] [skip ci] --- .../sink/strategy/cud/DeleteRelationship.kt | 6 --- .../kafka/sink/strategy/CudHandlerTest.kt | 51 +++++++++++++++++++ 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/sink/src/main/kotlin/org/neo4j/connectors/kafka/sink/strategy/cud/DeleteRelationship.kt b/sink/src/main/kotlin/org/neo4j/connectors/kafka/sink/strategy/cud/DeleteRelationship.kt index 2be89e6f..93d07e27 100644 --- a/sink/src/main/kotlin/org/neo4j/connectors/kafka/sink/strategy/cud/DeleteRelationship.kt +++ b/sink/src/main/kotlin/org/neo4j/connectors/kafka/sink/strategy/cud/DeleteRelationship.kt @@ -40,12 +40,6 @@ data class DeleteRelationship( ) } - if (start.ids.isEmpty() || end.ids.isEmpty()) { - throw InvalidDataException( - "'${Keys.FROM}' and '${Keys.TO}' must contain at least one ID property." - ) - } - val startParam = Cypher.parameter("start") val endParam = Cypher.parameter("end") val keysParam = Cypher.parameter("keys") diff --git a/sink/src/test/kotlin/org/neo4j/connectors/kafka/sink/strategy/CudHandlerTest.kt b/sink/src/test/kotlin/org/neo4j/connectors/kafka/sink/strategy/CudHandlerTest.kt index bce0c98b..9ba01d61 100644 --- a/sink/src/test/kotlin/org/neo4j/connectors/kafka/sink/strategy/CudHandlerTest.kt +++ b/sink/src/test/kotlin/org/neo4j/connectors/kafka/sink/strategy/CudHandlerTest.kt @@ -857,6 +857,57 @@ class CudHandlerTest : HandlerTest() { ) } + @Test + fun `should delete relationship without constraint on 'from' or 'to'`() { + val handler = CudHandler("my-topic", Renderer.getDefaultRenderer(), 100) + + val sinkMessage = + newMessage( + Schema.STRING_SCHEMA, + """ + { + "type": "relationship", + "op": "DELETE", + "rel_type": "RELATED_TO", + "from": { + "labels": ["Foo"], + "ids": {} + }, + "to": { + "labels": ["Bar"], + "ids": {} + } + } + """, + ) + handler.handle(listOf(sinkMessage)) shouldBe + listOf( + listOf( + ChangeQuery( + null, + null, + listOf(sinkMessage), + Query( + CypherParser.parse( + """ + MATCH (start:`Foo` {}) WITH start + MATCH (end:`Bar` {}) WITH start, end + MATCH (start)-[r:`RELATED_TO` {}]->(end) + DELETE r + """ + ) + .cypher, + mapOf( + "start" to mapOf("keys" to emptyMap()), + "end" to mapOf("keys" to emptyMap()), + "keys" to emptyMap() + ), + ), + ) + ) + ) + } + @ParameterizedTest @ValueSource(ints = [1, 6, 25, 100]) fun `should support mixed operations with different batch sizes`(batchSize: Int) {