Skip to content

Commit 4cf9ae2

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 eeb54cd commit 4cf9ae2

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;
@@ -267,13 +266,8 @@ protected QueryFragmentsAndParameters complete(@Nullable Condition condition, So
267266
.peek(p -> Neo4jQuerySupport.logParameterIfNull(p.nameOrIndex, p.value))
268267
.collect(Collectors.toMap(p -> p.nameOrIndex, p -> parameterConversion.apply(p.value, p.conversionOverride)));
269268

270-
if (queryType == Neo4jQueryType.DELETE) {
271-
Statement statement = CypherGenerator.INSTANCE.prepareDeleteOf(nodeDescription, condition, true);
272-
return new QueryFragmentsAndParameters(statement.getCypher(), convertedParameters);
273-
} else {
274-
QueryFragments queryFragments = createQueryFragments(condition, sort);
275-
return new QueryFragmentsAndParameters(nodeDescription, queryFragments, convertedParameters);
276-
}
269+
QueryFragments queryFragments = createQueryFragments(condition, sort);
270+
return new QueryFragmentsAndParameters(nodeDescription, queryFragments, convertedParameters);
277271
}
278272

279273
@NonNull
@@ -307,6 +301,9 @@ private QueryFragments createQueryFragments(@Nullable Condition condition, Sort
307301
queryFragments.setReturnExpression(Functions.count(Cypher.asterisk()), true);
308302
} else if (queryType == Neo4jQueryType.EXISTS) {
309303
queryFragments.setReturnExpression(Functions.count(Constants.NAME_OF_TYPED_ROOT_NODE.apply(nodeDescription)).gt(Cypher.literalOf(0)), true);
304+
} else if (queryType == Neo4jQueryType.DELETE) {
305+
queryFragments.setDeleteExpression(Constants.NAME_OF_TYPED_ROOT_NODE.apply(nodeDescription));
306+
queryFragments.setReturnExpression(Functions.count(Constants.NAME_OF_TYPED_ROOT_NODE.apply(nodeDescription)), true);
310307
} else {
311308
queryFragments.setReturnBasedOn(nodeDescription, includedProperties, isDistinct);
312309
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
@@ -933,6 +933,18 @@ void findBySameLabelRelationshipProperty(@Autowired PetRepository repository) {
933933
assertThat(pet.getFriends()).isNotEmpty();
934934
}
935935

936+
@Test
937+
void deleteByOwnPropertyAndRelationshipsProperty(@Autowired PetRepository repository) {
938+
939+
doWithSession(session -> session.run("CREATE (p1:Pet{name: 'Pet1'})-[:Has]->(p2:Pet{name: 'Pet2'})").consume());
940+
941+
repository.deleteByNameAndFriendsName("Pet1", "Pet2");
942+
doWithSession(session -> {
943+
assertThat(session.run("MATCH (p1:Pet{name: 'Pet'}) return p1").list()).hasSize(0);
944+
return null;
945+
});
946+
}
947+
936948
@Test
937949
void findBySameLabelRelationshipPropertyMultipleLevels(@Autowired PetRepository repository) {
938950
doWithSession(session -> session.run("CREATE (p1:Pet{name: 'Pet1'})-[:Has]->(p2:Pet{name: 'Pet2'})-[:Has]->(p3:Pet{name: 'Pet3'})").consume());
@@ -4321,6 +4333,8 @@ interface PetRepository extends Neo4jRepository<Pet, Long> {
43214333

43224334
Pet findByFriendsName(String friendName);
43234335

4336+
Long deleteByNameAndFriendsName(String name, String friendsName);
4337+
43244338
Pet findByFriendsFriendsName(String friendName);
43254339

43264340
long countByName(String name);

0 commit comments

Comments
 (0)