Skip to content

Commit b7cc8b3

Browse files
committed
GH-2685 - Fix delete query method with relationships.
Previously relationship related properties in the query method were missing in the MATCH part but the condition would get applied. This created an incorrect query string and failed on the server side. Non-invasive change to avoid regression in the other parts. Closes #2685
1 parent 50530d9 commit b7cc8b3

File tree

3 files changed

+28
-8
lines changed

3 files changed

+28
-8
lines changed

src/main/java/org/springframework/data/neo4j/repository/query/CypherQueryCreator.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
import org.neo4j.cypherdsl.core.Property;
4545
import org.neo4j.cypherdsl.core.RelationshipPattern;
4646
import org.neo4j.cypherdsl.core.SortItem;
47-
import org.neo4j.cypherdsl.core.Statement;
4847
import org.neo4j.driver.types.Point;
4948
import org.springframework.data.domain.Pageable;
5049
import org.springframework.data.domain.Range;
@@ -260,13 +259,8 @@ protected QueryFragmentsAndParameters complete(@Nullable Condition condition, So
260259
.peek(p -> Neo4jQuerySupport.logParameterIfNull(p.nameOrIndex, p.value))
261260
.collect(Collectors.toMap(p -> p.nameOrIndex, p -> parameterConversion.apply(p.value, p.conversionOverride)));
262261

263-
if (queryType == Neo4jQueryType.DELETE) {
264-
Statement statement = CypherGenerator.INSTANCE.prepareDeleteOf(nodeDescription, condition, true);
265-
return new QueryFragmentsAndParameters(statement.getCypher(), convertedParameters);
266-
} else {
267-
QueryFragments queryFragments = createQueryFragments(condition, sort);
268-
return new QueryFragmentsAndParameters(nodeDescription, queryFragments, convertedParameters);
269-
}
262+
QueryFragments queryFragments = createQueryFragments(condition, sort);
263+
return new QueryFragmentsAndParameters(nodeDescription, queryFragments, convertedParameters);
270264
}
271265

272266
@NonNull
@@ -300,6 +294,9 @@ private QueryFragments createQueryFragments(@Nullable Condition condition, Sort
300294
queryFragments.setReturnExpression(Functions.count(Cypher.asterisk()), true);
301295
} else if (queryType == Neo4jQueryType.EXISTS) {
302296
queryFragments.setReturnExpression(Functions.count(Constants.NAME_OF_TYPED_ROOT_NODE.apply(nodeDescription)).gt(Cypher.literalOf(0)), true);
297+
} else if (queryType == Neo4jQueryType.DELETE) {
298+
queryFragments.setDeleteExpression(Constants.NAME_OF_TYPED_ROOT_NODE.apply(nodeDescription));
299+
queryFragments.setReturnExpression(Functions.count(Constants.NAME_OF_TYPED_ROOT_NODE.apply(nodeDescription)), true);
303300
} else {
304301
queryFragments.setReturnBasedOn(nodeDescription, includedProperties, isDistinct);
305302
queryFragments.setOrderBy(Stream

src/main/java/org/springframework/data/neo4j/repository/query/QueryFragments.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ public final class QueryFragments {
5555
private ReturnTuple returnTuple;
5656
private boolean scalarValueReturn = false;
5757
private boolean renderConstantsAsParameters = false;
58+
private Expression deleteExpression;
5859

5960
public void addMatchOn(PatternElement match) {
6061
this.matchOn.add(match);
@@ -80,6 +81,10 @@ public void setReturnExpressions(Collection<Expression> expression) {
8081
this.returnExpressions = expression;
8182
}
8283

84+
public void setDeleteExpression(Expression expression) {
85+
this.deleteExpression = expression;
86+
}
87+
8388
public void setReturnExpression(Expression returnExpression, boolean isScalarValue) {
8489
this.returnExpressions = Collections.singletonList(returnExpression);
8590
this.scalarValueReturn = isScalarValue;
@@ -128,6 +133,10 @@ public Statement toStatement() {
128133

129134
StatementBuilder.OngoingReadingWithWhere matchWithWhere = match.where(condition);
130135

136+
if (deleteExpression != null) {
137+
matchWithWhere = (StatementBuilder.OngoingReadingWithWhere) matchWithWhere.detachDelete(deleteExpression);
138+
}
139+
131140
StatementBuilder.OngoingReadingAndReturn returnPart = isDistinctReturn()
132141
? matchWithWhere.returningDistinct(getReturnExpressions())
133142
: matchWithWhere.returning(getReturnExpressions());

src/test/java/org/springframework/data/neo4j/integration/imperative/RepositoryIT.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,18 @@ void findBySameLabelRelationshipProperty(@Autowired PetRepository repository) {
940940
assertThat(pet.getFriends()).isNotEmpty();
941941
}
942942

943+
@Test
944+
void deleteByOwnPropertyAndRelationshipsProperty(@Autowired PetRepository repository) {
945+
946+
doWithSession(session -> session.run("CREATE (p1:Pet{name: 'Pet1'})-[:Has]->(p2:Pet{name: 'Pet2'})").consume());
947+
948+
repository.deleteByNameAndFriendsName("Pet1", "Pet2");
949+
doWithSession(session -> {
950+
assertThat(session.run("MATCH (p1:Pet{name: 'Pet'}) return p1").list()).hasSize(0);
951+
return null;
952+
});
953+
}
954+
943955
@Test
944956
void findBySameLabelRelationshipPropertyMultipleLevels(@Autowired PetRepository repository) {
945957
doWithSession(session -> session.run("CREATE (p1:Pet{name: 'Pet1'})-[:Has]->(p2:Pet{name: 'Pet2'})-[:Has]->(p3:Pet{name: 'Pet3'})").consume());
@@ -4364,6 +4376,8 @@ interface PetRepository extends Neo4jRepository<Pet, Long> {
43644376

43654377
Pet findByFriendsName(String friendName);
43664378

4379+
Long deleteByNameAndFriendsName(String name, String friendsName);
4380+
43674381
Pet findByFriendsFriendsName(String friendName);
43684382

43694383
long countByName(String name);

0 commit comments

Comments
 (0)