diff --git a/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/Person.java b/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/Person.java index fbbea1349..2dd884350 100644 --- a/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/Person.java +++ b/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/Person.java @@ -32,7 +32,7 @@ import java.util.Set; @NodeEntity public class Person { - public static final String NAME_INDEX = "name_index"; + public static final String NAME_INDEX = "name-index"; @GraphId private Long graphId; diff --git a/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/query/QueryEngineTest.java b/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/query/QueryEngineTest.java index 23ea57bbb..227f62a1b 100644 --- a/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/query/QueryEngineTest.java +++ b/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/query/QueryEngineTest.java @@ -91,7 +91,7 @@ public class QueryEngineTest extends EntityTestBase { @Test public void testQueryListOfTypeNode() throws Exception { - final String queryString = "start person=node:name_index(name={name}) match (person) <-[:boss]- (boss) return boss"; + final String queryString = "start person=node:`name-index`(name={name}) match (person) <-[:boss]- (boss) return boss"; final Result> queryResult = queryEngine.query(queryString, michaelsName()); final Collection result = IteratorUtil.asCollection(queryResult.to(Node.class)); @@ -100,7 +100,7 @@ public class QueryEngineTest extends EntityTestBase { @SuppressWarnings("unchecked") @Test public void testQueryListOfTypePerson() throws Exception { - final String queryString = "start person=node:name_index(name={name}) match (person) <-[:boss]- (boss) return boss"; + final String queryString = "start person=node:`name-index`(name={name}) match (person) <-[:boss]- (boss) return boss"; final Collection result = IteratorUtil.asCollection(queryEngine.query(queryString, michaelsName()).to(Person.class, new EntityResultConverter(conversionService, template))); assertEquals(asList(testTeam.emil),result); @@ -112,7 +112,7 @@ public class QueryEngineTest extends EntityTestBase { @Test public void testQuerySingleOfTypePerson() throws Exception { - final String queryString = "start person=node:name_index(name={name}) match (person) <-[:boss]- (boss) return boss"; + final String queryString = "start person=node:`name-index`(name={name}) match (person) <-[:boss]- (boss) return boss"; final Person result = queryEngine.query(queryString, michaelsName()).to(Person.class, new EntityResultConverter,Person>(conversionService, template)).single(); assertEquals(testTeam.emil,result); @@ -195,7 +195,7 @@ public class QueryEngineTest extends EntityTestBase { } @Test public void testQueryListWithCustomConverter() throws Exception { - final String queryString = "start person=node:name_index(name={name}) match (person) <-[:boss]- (boss) return boss"; + final String queryString = "start person=node:`name-index`(name={name}) match (person) <-[:boss]- (boss) return boss"; final Collection result = IteratorUtil.asCollection(queryEngine.query(queryString, michaelsName()).to(String.class, new ResultConverter.ResultConverterAdapter, String>() { @Override public String convert(Map row, Class target) { @@ -208,14 +208,14 @@ public class QueryEngineTest extends EntityTestBase { @Test public void testQueryForObjectAsString() throws Exception { - final String queryString = "start person=node:name_index(name={name}) match (person) <-[:persons]- (team) return team.name"; + final String queryString = "start person=node:`name-index`(name={name}) match (person) <-[:persons]- (team) return team.name"; final String result = queryEngine.query(queryString, michaelsName()).to(String.class).single(); assertEquals(testTeam.sdg.getName(),result); } @Test public void testQueryForObjectAsEnum() throws Exception { - final String queryString = "start person=node:name_index(name={name}) return person.personality"; + final String queryString = "start person=node:`name-index`(name={name}) return person.personality"; final Personality result = queryEngine.query(queryString, michaelsName()).to(Personality.class).single(); assertEquals(michael.getPersonality(),result); diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/CypherQueryBuilder.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/CypherQueryBuilder.java index 9e78cb6c4..0c60c5037 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/CypherQueryBuilder.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/CypherQueryBuilder.java @@ -15,11 +15,6 @@ */ package org.springframework.data.neo4j.repository.query; -import static org.springframework.util.StringUtils.*; - -import java.util.ArrayList; -import java.util.List; - import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.mapping.context.MappingContext; @@ -29,6 +24,11 @@ import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty; import org.springframework.data.repository.query.parser.Part; import org.springframework.util.Assert; +import java.util.ArrayList; +import java.util.List; + +import static org.springframework.util.StringUtils.*; + /** * Value object to create Cypher queries. * @@ -133,7 +133,7 @@ class CypherQueryBuilder implements CypherQueryDefinition { builder.append(" where ").append(whereClauses); } - builder.append(" return ").append(variableContext.getVariableFor(entity)); + builder.append(" return ").append(String.format(QueryTemplates.VARIABLE, variableContext.getVariableFor(entity))); return builder.toString(); } diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/MatchClause.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/MatchClause.java index 9f6ef77fa..a954a54da 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/MatchClause.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/MatchClause.java @@ -65,11 +65,20 @@ class MatchClause { private String matchPattern(VariableContext variableContext, PersistentPropertyPath relPath) { if (relPath.getLength() == 1) { final Neo4jPersistentProperty property = relPath.getBaseProperty(); - return variableContext.getVariableFor(property.getOwner()) + QueryTemplates.getArrow(property.getRelationshipInfo()) - + variableContext.getVariableFor(relPath); + return formatMatch(variableContext.getVariableFor(property.getOwner()), + QueryTemplates.getArrow(property.getRelationshipInfo()), + variableContext.getVariableFor(relPath)); } final RelationshipInfo info = relPath.getLeafProperty().getRelationshipInfo(); - return matchPattern(variableContext, relPath.getParentPath()) + QueryTemplates.getArrow(info) - + variableContext.getVariableFor(relPath); + return formatMatch2(matchPattern(variableContext, relPath.getParentPath()), + QueryTemplates.getArrow(info), + variableContext.getVariableFor(relPath)); + } + + private String formatMatch(String first, String arrow, String second) { + return String.format(QueryTemplates.MATCH_CLAUSE, first, arrow, second); + } + private String formatMatch2(String first, String arrow, String second) { + return String.format(QueryTemplates.MATCH_CLAUSE2, first, arrow, second); } } \ No newline at end of file diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/QueryTemplates.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/QueryTemplates.java index e1e5c2070..9b9267b4d 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/QueryTemplates.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/QueryTemplates.java @@ -27,18 +27,21 @@ public abstract class QueryTemplates { public static final String PARAMETER = "%d"; public static final String PARAMETER_INDEX_QUERY = "%s:%s"; + public static final String VARIABLE = "`%s`"; public static final String PLACEHOLDER = String.format("{%s}", PARAMETER); - private static final String DIRECTION_INCOMING = "<-[:%s]-"; - private static final String DIRECTION_OUTGOING = "-[:%s]->"; - private static final String DIRECTION_BOTH = "-[:%s]-"; + private static final String DIRECTION_INCOMING = "<-[:`%s`]-"; + private static final String DIRECTION_OUTGOING = "-[:`%s`]->"; + private static final String DIRECTION_BOTH = "-[:`%s`]-"; + static final String MATCH_CLAUSE = "`%s`%s`%s`"; + static final String MATCH_CLAUSE2 = "%s%s`%s`"; - static final String DEFAULT_START_CLAUSE = "%s=node:__types__(className=\"%s\")"; + static final String DEFAULT_START_CLAUSE = "`%s`=node:__types__(className=\"%s\")"; static final String SKIP_LIMIT = " skip %d limit %d"; - static final String START_CLAUSE = "%s=node:%s(%s=" + PLACEHOLDER + ")"; - static final String START_CLAUSE_FULLTEXT = "%s=node:%s(" + PLACEHOLDER + ")"; - static final String WHERE_CLAUSE_1 = "%s.%s %s " + PLACEHOLDER; - static final String WHERE_CLAUSE_0 = "%s.%s %s "; + static final String START_CLAUSE = "`%s`=node:`%s`(`%s`=" + PLACEHOLDER + ")"; + static final String START_CLAUSE_FULLTEXT = "`%s`=node:`%s`(" + PLACEHOLDER + ")"; + static final String WHERE_CLAUSE_1 = "`%s`.`%s` %s " + PLACEHOLDER; + static final String WHERE_CLAUSE_0 = "`%s`.`%s` %s "; static final String SORT_CLAUSE = "%s %s"; static final String ORDER_BY_CLAUSE = " order by %s"; diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/model/Person.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/model/Person.java index 83ff520e4..678fdecdd 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/model/Person.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/model/Person.java @@ -32,7 +32,7 @@ import java.util.Set; @NodeEntity public class Person { - public static final String NAME_INDEX = "name_index"; + public static final String NAME_INDEX = "name-index"; public static final org.neo4j.graphdb.RelationshipType KNOWS = DynamicRelationshipType.withName("knows"); @GraphId private Long graphId; diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/query/CypherQueryBuilderUnitTests.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/query/CypherQueryBuilderUnitTests.java index 9962ebf58..fd103ae63 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/query/CypherQueryBuilderUnitTests.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/query/CypherQueryBuilderUnitTests.java @@ -15,9 +15,6 @@ */ package org.springframework.data.neo4j.repository.query; -import static org.hamcrest.CoreMatchers.*; -import static org.junit.Assert.*; - import org.junit.Before; import org.junit.Test; import org.springframework.data.domain.PageRequest; @@ -26,6 +23,9 @@ import org.springframework.data.domain.Sort; import org.springframework.data.neo4j.support.mapping.Neo4jMappingContext; import org.springframework.data.repository.query.parser.Part; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + /** * Unit tests for {@link CypherQueryBuilder}. * @@ -35,7 +35,7 @@ public class CypherQueryBuilderUnitTests { CypherQueryBuilder query; private final String CLASS_NAME = Person.class.getName(); - private String DEFAULT_START_CLAUSE = "start person=node:__types__(className=\"" + CLASS_NAME + "\")"; + private String DEFAULT_START_CLAUSE = "start `person`=node:__types__(className=\"" + CLASS_NAME + "\")"; @Before public void setUp() { @@ -49,7 +49,7 @@ public class CypherQueryBuilderUnitTests { Part part = new Part("name", Person.class); query.addRestriction(part); - assertThat(query.toString(), is("start person=node:Person(name={0}) return person")); + assertThat(query.toString(), is("start `person`=node:`Person`(`name`={0}) return `person`")); } @Test @@ -58,7 +58,7 @@ public class CypherQueryBuilderUnitTests { Part part = new Part("titleLike", Person.class); query.addRestriction(part); - assertThat(query.toString(), is("start person=node:title({0}) return person")); + assertThat(query.toString(), is("start `person`=node:`title`({0}) return `person`")); } @Test public void createsQueryForLikeProperty() { @@ -66,7 +66,7 @@ public class CypherQueryBuilderUnitTests { Part part = new Part("infoLike", Person.class); query.addRestriction(part); - assertThat(query.toString(), is(DEFAULT_START_CLAUSE+" where person.info =~ {0} return person")); + assertThat(query.toString(), is(DEFAULT_START_CLAUSE+" where `person`.`info` =~ {0} return `person`")); } @Test public void createsQueryForGreaterThanPropertyReference() { @@ -74,7 +74,7 @@ public class CypherQueryBuilderUnitTests { Part part = new Part("ageGreaterThan", Person.class); query.addRestriction(part); - assertThat(query.toString(), is(DEFAULT_START_CLAUSE+" where person.age > {0} return person")); + assertThat(query.toString(), is(DEFAULT_START_CLAUSE+" where `person`.`age` > {0} return `person`")); } @Test public void createsQueryForTwoPropertyExpressions() { @@ -82,7 +82,7 @@ public class CypherQueryBuilderUnitTests { query.addRestriction(new Part("ageGreaterThan", Person.class)); query.addRestriction(new Part("info", Person.class)); - assertThat(query.toString(), is(DEFAULT_START_CLAUSE+" where person.age > {0} and person.info = {1} return person")); + assertThat(query.toString(), is(DEFAULT_START_CLAUSE+" where `person`.`age` > {0} and `person`.`info` = {1} return `person`")); } @Test @@ -91,7 +91,7 @@ public class CypherQueryBuilderUnitTests { Part part = new Part("ageIsNull", Person.class); query.addRestriction(part); - assertThat(query.toString(), is(DEFAULT_START_CLAUSE+" where person.age is null return person")); + assertThat(query.toString(), is(DEFAULT_START_CLAUSE+" where `person`.`age` is null return `person`")); } @Test @@ -100,7 +100,7 @@ public class CypherQueryBuilderUnitTests { Part part = new Part("group.name", Person.class); query.addRestriction(part); - assertThat(query.toString(), is("start person_group=node:Group(name={0}) match person<-[:members]-person_group return person")); + assertThat(query.toString(), is("start `person_group`=node:`Group`(`name`={0}) match `person`<-[:`members`]-`person_group` return `person`")); } @Test @@ -110,7 +110,7 @@ public class CypherQueryBuilderUnitTests { query.addRestriction(new Part("group.name", Person.class)); assertThat(query.toString(), - is("start person=node:Person(name={0}), person_group=node:Group(name={1}) match person<-[:members]-person_group return person")); + is("start `person`=node:`Person`(`name`={0}), `person_group`=node:`Group`(`name`={1}) match `person`<-[:`members`]-`person_group` return `person`")); } @Test @@ -119,12 +119,12 @@ public class CypherQueryBuilderUnitTests { query.addRestriction(new Part("age", Person.class)); final String className = Person.class.getName(); - assertThat(query.toString(), is(DEFAULT_START_CLAUSE +" where person.age = {0} return person")); + assertThat(query.toString(), is(DEFAULT_START_CLAUSE +" where `person`.`age` = {0} return `person`")); } @Test public void createsSimpleTraversalClauseCorrectly() { query.addRestriction(new Part("group", Person.class)); - assertThat(query.toString(), is(DEFAULT_START_CLAUSE + " match person<-[:members]-person_group return person")); + assertThat(query.toString(), is(DEFAULT_START_CLAUSE + " match `person`<-[:`members`]-`person_group` return `person`")); } @@ -138,29 +138,29 @@ public class CypherQueryBuilderUnitTests { System.out.println(query.toString()); assertThat(query.toString(), is( - "start person=node:Person(name={0}), person_group=node:Group(name={1}) " + - "match person<-[:members]-person_group, person<-[:members]-person_group-[:members]->person_group_members " + - "where person.age > {2} and person_group_members.age = {3} " + - "return person" + "start `person`=node:`Person`(`name`={0}), `person_group`=node:`Group`(`name`={1}) " + + "match `person`<-[:`members`]-`person_group`, `person`<-[:`members`]-`person_group`-[:`members`]->`person_group_members` " + + "where `person`.`age` > {2} and `person_group_members`.`age` = {3} " + + "return `person`" )); } @Test public void buildsQueryWithSort() { query.addRestriction(new Part("name",Person.class)); - assertThat(query.toString(new Sort("person.name")), is("start person=node:Person(name={0}) return person order by person.name ASC")); + assertThat(query.toString(new Sort("person.name")), is("start `person`=node:`Person`(`name`={0}) return `person` order by person.name ASC")); } @Test public void buildsQueryWithTwoSorts() { query.addRestriction(new Part("name",Person.class)); Sort sort = new Sort(new Sort.Order("person.name"),new Sort.Order(Sort.Direction.DESC, "person.age")); - assertThat(query.toString(sort), is("start person=node:Person(name={0}) return person order by person.name ASC,person.age DESC")); + assertThat(query.toString(sort), is("start `person`=node:`Person`(`name`={0}) return `person` order by person.name ASC,person.age DESC")); } @Test public void buildsQueryWithPage() { query.addRestriction(new Part("name",Person.class)); Pageable pageable = new PageRequest(3,10,new Sort("person.name")); - assertThat(query.toString(pageable), is("start person=node:Person(name={0}) return person order by person.name ASC skip 30 limit 10")); + assertThat(query.toString(pageable), is("start `person`=node:`Person`(`name`={0}) return `person` order by person.name ASC skip 30 limit 10")); } }