package org.infinispan.query.dsl.embedded.impl; import static org.assertj.core.api.Assertions.assertThat; import java.util.HashMap; import java.util.Map; import org.apache.lucene.search.Sort; import org.apache.lucene.search.SortField; import org.hibernate.search.engine.integration.impl.ExtendedSearchIntegrator; import org.hibernate.search.exception.SearchException; import org.hibernate.search.testsupport.junit.SearchFactoryHolder; import org.infinispan.objectfilter.ParsingException; import org.infinispan.objectfilter.impl.syntax.parser.IckleParsingResult; import org.infinispan.objectfilter.impl.syntax.parser.IckleParser; import org.infinispan.objectfilter.impl.syntax.parser.ReflectionEntityNamesResolver; import org.infinispan.query.dsl.embedded.impl.model.Employee; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; /** * Test the parsing and transformation of Ickle queries to Lucene queries. * * @author anistor@redhat.com * @since 9.0 */ public class LuceneTransformationTest { @Rule public SearchFactoryHolder factoryHolder = new SearchFactoryHolder(Employee.class); @Rule public ExpectedException expectedException = ExpectedException.none(); @Test public void testRaiseExceptionDueToUnknownAlias() { expectedException.expect(ParsingException.class); expectedException.expectMessage("ISPN028502: Unknown alias: a."); parseAndTransform("from org.infinispan.query.dsl.embedded.impl.model.Employee e where a.name = 'same'"); } @Test public void testMatchAllQuery() { assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee", "*:*"); assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e", "*:*"); assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e", "*:*"); assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where true", "*:*"); } @Test public void testRejectAllQuery() { assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where false", "-*:* #*:*"); //TODO [anistor] maybe this should be "-*:*" } @Test public void testFullTextKeyword() { assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.text : 'bicycle'", "text:bicycle"); } @Test public void testFullTextWildcard() { assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.text : 'geo*e'", "text:geo*e"); } @Test public void testFullTextFuzzy() { assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.text : 'jonh'~2", "text:jonh~2"); } @Test public void testFullTextPhrase() { assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.text : 'twisted cables'", "text:\"twisted cables\""); } @Test public void testFullTextRegexp() { assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.text : /te?t/", "text:/te?t/"); } @Test public void testFullTextRange() { assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.text : ['AAA' 'ZZZ']", "text:[aaa TO zzz]"); assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.text : ['AAA' to 'ZZZ']", "text:[aaa TO zzz]"); assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.text : [* to 'eeee']", "text:[* TO eeee]"); assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.text : ['eeee' to *]", "text:[eeee TO *]"); assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.text : [* *]", "text:[* TO *]"); } @Test public void testFullTextFieldBoost() { assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.text : 'foo'^3.0'", "text:foo^3.0"); assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.text : ('foo')^3.0'", "text:foo^3.0"); assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.text : ('foo' and 'bar')^3.0'", "(+text:foo +text:bar)^3.0"); assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.text : 'foo'^3.0 || e.analyzedInfo : 'bar'", "text:foo^3.0 analyzedInfo:bar"); } @Test public void testFullTextFieldOccur() { assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.text : (-'foo') ", "-text:foo #*:*"); assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.text : (-'foo' +'bar')", "(-text:foo) (+text:bar)"); assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where not e.text : (-'foo' +'bar')", "-((-text:foo) (+text:bar)) #*:*"); // TODO [anistor] fix this // assertGeneratedLuceneQuery( // "from org.infinispan.query.dsl.embedded.impl.model.Employee e where !e.text : (-'foo' +'bar')", // "-((-text:foo) (+text:bar)) #*:*"); assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.text : (-'foo' '*')", "(-text:foo) text:*"); } @Test public void testRestrictedQueryUsingSelect() { assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name = 'same' or e.id = 5", "name:same id:5"); assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name = 'same' and e.id = 5", "+name:same +id:5"); assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name = 'same' and not e.id = 5", "+name:same -id:5"); assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name = 'same' or not e.id = 5", "name:same (-id:5 #*:*)"); assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where not e.id = 5", "-id:5 #*:*"); assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.id != 5", "-id:5 #*:*"); } @Test public void testFieldMapping() { assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.someMoreInfo = 'foo'", "someMoreInfo:foo"); assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.sameInfo = 'foo'", "sameInfo:foo"); } @Test public void testWrongFieldName() { expectedException.expect(SearchException.class); expectedException.expectMessage("Unable to find field otherInfo in org.infinispan.query.dsl.embedded.impl.model.Employee"); parseAndTransform("from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.otherInfo = 'foo'"); } @Test public void testProjectionQuery() { LuceneQueryParsingResult<Class<?>> parsingResult = parseAndTransform("select e.id, e.name from org.infinispan.query.dsl.embedded.impl.model.Employee e"); assertThat(parsingResult.getQuery().toString()).isEqualTo("*:*"); assertThat(parsingResult.getProjections()).isEqualTo(new String[]{"id", "name"}); } @Test public void testEmbeddedProjectionQuery() { LuceneQueryParsingResult<Class<?>> parsingResult = parseAndTransform("select e.author.name from org.infinispan.query.dsl.embedded.impl.model.Employee e"); assertThat(parsingResult.getQuery().toString()).isEqualTo("*:*"); assertThat(parsingResult.getProjections()).isEqualTo(new String[]{"author.name"}); } @Test public void testNestedEmbeddedProjectionQuery() { LuceneQueryParsingResult<Class<?>> parsingResult = parseAndTransform("select e.author.address.street from org.infinispan.query.dsl.embedded.impl.model.Employee e"); assertThat(parsingResult.getQuery().toString()).isEqualTo("*:*"); assertThat(parsingResult.getProjections()).isEqualTo(new String[]{"author.address.street"}); } @Test public void testQueryWithUnqualifiedPropertyReferences() { assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where name = 'same' and not id = 5", "+name:same -id:5"); } @Test public void testNegatedQuery() { assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where NOT e.name = 'same'", "-name:same #*:*"); // JPQL syntax assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name <> 'same'", "-name:same #*:*"); // HQL syntax assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name != 'same'", "-name:same #*:*"); } @Test public void testNegatedQueryOnNumericProperty() { assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.position <> 3", "-position:[3 TO 3] #*:*"); } @Test public void testNegatedRangeQuery() { assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee where name = 'Bob' and not position between 1 and 3", "+name:Bob -position:[1 TO 3]"); assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name = 'Bob' and not e.position between 1 and 3", "+name:Bob -position:[1 TO 3]"); } @Test public void testQueryWithNamedParameter() { Map<String, Object> namedParameters = new HashMap<>(); namedParameters.put("nameParameter", "Bob"); assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee where name = :nameParameter", namedParameters, "name:Bob"); assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name = :nameParameter", namedParameters, "name:Bob"); } @Test public void testBooleanQuery() { assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name = 'same' or (e.id = 4 and e.name = 'Bob')", "name:same (+id:4 +name:Bob)"); } @Test public void testBooleanQueryUsingSelect() { assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name = 'same' or (e.id = 4 and e.name = 'Bob')", "name:same (+id:4 +name:Bob)"); } @Test public void testBetweenQuery() { assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name between 'aaa' and 'zzz'", "name:[aaa TO zzz]"); } @Test public void testNotBetweenQuery() { assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name not between 'aaa' and 'zzz'", "-name:[aaa TO zzz] #*:*"); } @Test public void testNumericNotBetweenQuery() { assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where not e.position between 1 and 3", "-position:[1 TO 3] #*:*"); } @Test public void testBetweenQueryForCharacterLiterals() { assertGeneratedLuceneQuery("select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name between 'a' and 'z'", "name:[a TO z]"); } @Test public void testBetweenQueryWithNamedParameters() { Map<String, Object> namedParameters = new HashMap<>(); namedParameters.put("p1", "aaa"); namedParameters.put("p2", "zzz"); assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name between :p1 and :p2", namedParameters, "name:[aaa TO zzz]"); } @Test public void testNumericBetweenQuery() { Map<String, Object> namedParameters = new HashMap<>(); namedParameters.put("p1", 10L); namedParameters.put("p2", 20L); assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.position between :p1 and :p2", namedParameters, "position:[10 TO 20]"); } @Test public void testQueryWithEmbeddedPropertyInFromClause() { assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.author.name = 'Bob'", "author.name:Bob"); } @Test public void testLessThanQuery() { assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.position < 100", "position:[* TO 100}"); } @Test public void testLessThanOrEqualsToQuery() { assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.position <= 100", "position:[* TO 100]"); } @Test public void testGreaterThanOrEqualsToQuery() { assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee where position >= 100", "position:[100 TO *]"); assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.position >= 100", "position:[100 TO *]"); } @Test public void testGreaterThanQuery() { assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee where position > 100", "position:{100 TO *]"); assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.position > 100", "position:{100 TO *]"); } @Test public void testInQuery() { assertGeneratedLuceneQuery( "from org.infinispan.query.dsl.embedded.impl.model.Employee where name in ('Bob', 'Alice')", "name:Bob name:Alice"); assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name in ('Bob', 'Alice')", "name:Bob name:Alice"); assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.position in (10, 20, 30, 40)", "position:[10 TO 10] position:[20 TO 20] position:[30 TO 30] position:[40 TO 40]"); } @Test public void testInQueryWithNamedParameters() { Map<String, Object> namedParameters = new HashMap<>(); namedParameters.put("name1", "Bob"); namedParameters.put("name2", "Alice"); assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name in (:name1, :name2)", namedParameters, "name:Bob name:Alice"); namedParameters = new HashMap<>(); namedParameters.put("pos1", 10); namedParameters.put("pos2", 20); namedParameters.put("pos3", 30); namedParameters.put("pos4", 40); assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.position in (:pos1, :pos2, :pos3, :pos4)", namedParameters, "position:[10 TO 10] position:[20 TO 20] position:[30 TO 30] position:[40 TO 40]"); } @Test public void testNotInQuery() { assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name not in ('Bob', 'Alice')", "-(name:Bob name:Alice) #*:*"); assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.position not in (10, 20, 30, 40)", "-(position:[10 TO 10] position:[20 TO 20] position:[30 TO 30] position:[40 TO 40]) #*:*"); } @Test public void testLikeQuery() { assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name LIKE 'Al_ce'", "name:Al?ce"); assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name LIKE 'Ali%'", "name:Ali*"); assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name LIKE 'Ali%%'", "name:Ali**"); assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name LIKE '_l_ce'", "name:?l?ce"); assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name LIKE '___ce'", "name:???ce"); assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name LIKE '_%_ce'", "name:?*?ce"); assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name LIKE 'Alice in wonderl%'", "name:Alice in wonderl*"); } @Test public void testNotLikeQuery() { assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name NOT LIKE 'Al_ce'", "-name:Al?ce #*:*"); assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name NOT LIKE 'Ali%'", "-name:Ali* #*:*"); assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name NOT LIKE '_l_ce' and not (e.title LIKE '%goo' and e.position = '5')", "-name:?l?ce -(+title:*goo +position:[5 TO 5]) #*:*"); } @Test public void testIsNullQuery() { assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name IS null", "name:_null_"); } @Test public void testIsNullQueryForEmbeddedEntity() { assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.author IS null", "author:_null_"); } @Test public void testIsNotNullQuery() { assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name IS NOT null", "-name:_null_ #*:*"); } @Test public void testCollectionOfEmbeddableQuery() { assertGeneratedLuceneQuery( "select e from org.infinispan.query.dsl.embedded.impl.model.Employee e JOIN e.contactDetails d WHERE d.email = 'ninja647@mailinator.com' ", "contactDetails.email:ninja647@mailinator.com"); } @Test public void testCollectionOfEmbeddableInEmbeddedQuery() { assertGeneratedLuceneQuery( "SELECT e FROM org.infinispan.query.dsl.embedded.impl.model.Employee e " + " JOIN e.contactDetails d" + " JOIN d.address.alternatives as a " + "WHERE a.postCode = '90210' ", "contactDetails.address.alternatives.postCode:90210"); } @Test public void testRaiseExceptionDueToUnknownQualifiedProperty() { expectedException.expect(ParsingException.class); expectedException.expectMessage("ISPN028501: The type org.infinispan.query.dsl.embedded.impl.model.Employee has no property named 'foobar'."); parseAndTransform("from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.foobar = 'same'"); } @Test public void testRaiseExceptionDueToUnknownUnqualifiedProperty() { expectedException.expect(ParsingException.class); expectedException.expectMessage("ISPN028501: The type org.infinispan.query.dsl.embedded.impl.model.Employee has no property named 'foobar'."); parseAndTransform("from org.infinispan.query.dsl.embedded.impl.model.Employee e where foobar = 'same'"); } @Test public void testRaiseExceptionDueToAnalyzedPropertyInFromClause() { expectedException.expect(ParsingException.class); expectedException.expectMessage("ISPN028522: No relational queries can be applied to property 'text' in type org.infinispan.query.dsl.embedded.impl.model.Employee since the property is analyzed."); parseAndTransform("from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.text = 'foo'"); } @Test public void testRaiseExceptionDueToUnknownPropertyInSelectClause() { expectedException.expect(ParsingException.class); expectedException.expectMessage("ISPN028501: The type org.infinispan.query.dsl.embedded.impl.model.Employee has no property named 'foobar'."); parseAndTransform("select e.foobar from org.infinispan.query.dsl.embedded.impl.model.Employee e"); } @Test public void testRaiseExceptionDueToUnknownPropertyInEmbeddedSelectClause() { expectedException.expect(ParsingException.class); expectedException.expectMessage("ISPN028501: The type org.infinispan.query.dsl.embedded.impl.model.Employee has no property named 'foo'."); parseAndTransform("select e.author.foo from org.infinispan.query.dsl.embedded.impl.model.Employee e"); } @Test public void testRaiseExceptionDueToSelectionOfCompleteEmbeddedEntity() { expectedException.expect(ParsingException.class); expectedException.expectMessage("ISPN028503: Property author can not be selected from type org.infinispan.query.dsl.embedded.impl.model.Employee since it is an embedded entity."); parseAndTransform("select e.author from org.infinispan.query.dsl.embedded.impl.model.Employee e"); } @Test public void testRaiseExceptionDueToUnqualifiedSelectionOfCompleteEmbeddedEntity() { expectedException.expect(ParsingException.class); expectedException.expectMessage("ISPN028503: Property author can not be selected from type org.infinispan.query.dsl.embedded.impl.model.Employee since it is an embedded entity."); parseAndTransform("select author from org.infinispan.query.dsl.embedded.impl.model.Employee e"); } @Test public void testDetermineTargetEntityType() { LuceneQueryParsingResult<Class<?>> result = parseAndTransform("select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name = 'same' and not e.id = 5"); assertThat(result.getTargetEntityMetadata()).isSameAs(Employee.class); assertThat(result.getTargetEntityName()).isEqualTo("org.infinispan.query.dsl.embedded.impl.model.Employee"); result = parseAndTransform("select e from org.infinispan.query.dsl.embedded.impl.model.Employee e"); assertThat(result.getTargetEntityMetadata()).isSameAs(Employee.class); assertThat(result.getTargetEntityName()).isEqualTo("org.infinispan.query.dsl.embedded.impl.model.Employee"); } @Test public void testBuildOneFieldSort() { LuceneQueryParsingResult<Class<?>> result = parseAndTransform("select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name = 'same' order by e.title"); Sort sort = result.getSort(); assertThat(sort).isNotNull(); assertThat(sort.getSort().length).isEqualTo(1); assertThat(sort.getSort()[0].getField()).isEqualTo("title"); assertThat(sort.getSort()[0].getReverse()).isEqualTo(false); assertThat(sort.getSort()[0].getType()).isEqualTo(SortField.Type.STRING); } @Test public void testBuildTwoFieldsSort() { LuceneQueryParsingResult<Class<?>> result = parseAndTransform("select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name = 'same' order by e.title, e.position DESC"); Sort sort = result.getSort(); assertThat(sort).isNotNull(); assertThat(sort.getSort().length).isEqualTo(2); assertThat(sort.getSort()[0].getField()).isEqualTo("title"); assertThat(sort.getSort()[0].getReverse()).isEqualTo(false); assertThat(sort.getSort()[0].getType()).isEqualTo(SortField.Type.STRING); assertThat(sort.getSort()[1].getField()).isEqualTo("position"); assertThat(sort.getSort()[1].getReverse()).isEqualTo(true); assertThat(sort.getSort()[1].getType()).isEqualTo(SortField.Type.LONG); } @Test public void testBuildSortForNullEncoding() { LuceneQueryParsingResult<Class<?>> result = parseAndTransform("select e from org.infinispan.query.dsl.embedded.impl.model.Employee e order by e.code DESC"); Sort sort = result.getSort(); assertThat(sort).isNotNull(); assertThat(sort.getSort().length).isEqualTo(1); assertThat(sort.getSort()[0].getField()).isEqualTo("code"); assertThat(sort.getSort()[0].getType()).isEqualTo(SortField.Type.LONG); } @Test public void testRaiseExceptionDueToUnrecognizedSortDirection() { expectedException.expect(ParsingException.class); expectedException.expectMessage("ISPN028526: Invalid query: select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name = 'same' order by e.title DESblah, e.name ASC;"); parseAndTransform("select e from org.infinispan.query.dsl.embedded.impl.model.Employee e where e.name = 'same' order by e.title DESblah, e.name ASC"); } @Test public void testBeAbleToJoinOnCollectionOfEmbedded() { LuceneQueryParsingResult<Class<?>> result = parseAndTransform("select d.email from org.infinispan.query.dsl.embedded.impl.model.Employee e JOIN e.contactDetails d"); assertThat(result.getQuery().toString()).isEqualTo("*:*"); assertThat(result.getProjections()).containsOnly("contactDetails.email"); } @Test public void testBeAbleToJoinOnCollectionOfEmbeddedWithEmbedded() { LuceneQueryParsingResult<Class<?>> result = parseAndTransform("select d.email from org.infinispan.query.dsl.embedded.impl.model.Employee e JOIN e.contactDetails d WHERE d.address.postCode='EA123'"); assertThat(result.getQuery().toString()).isEqualTo("contactDetails.address.postCode:EA123"); assertThat(result.getProjections()).containsOnly("contactDetails.email"); } @Test public void testBeAbleToJoinOnCollectionOfEmbeddedWithEmbeddedAndUseInOperator() { LuceneQueryParsingResult<Class<?>> result = parseAndTransform("select d.email from org.infinispan.query.dsl.embedded.impl.model.Employee e JOIN e.contactDetails d WHERE d.address.postCode IN ('EA123')"); assertThat(result.getQuery().toString()).isEqualTo("contactDetails.address.postCode:EA123"); assertThat(result.getProjections()).containsOnly("contactDetails.email"); } @Test public void testBeAbleToJoinOnCollectionOfEmbeddedWithEmbeddedAndUseBetweenOperator() { LuceneQueryParsingResult<Class<?>> result = parseAndTransform("select d.email from org.infinispan.query.dsl.embedded.impl.model.Employee e JOIN e.contactDetails d WHERE d.address.postCode BETWEEN '0000' AND 'ZZZZ'"); assertThat(result.getQuery().toString()).isEqualTo("contactDetails.address.postCode:[0000 TO ZZZZ]"); assertThat(result.getProjections()).containsOnly("contactDetails.email"); } @Test public void testBeAbleToJoinOnCollectionOfEmbeddedWithEmbeddedAndUseGreaterOperator() { LuceneQueryParsingResult<Class<?>> result = parseAndTransform("select d.email from org.infinispan.query.dsl.embedded.impl.model.Employee e JOIN e.contactDetails d WHERE d.address.postCode > '0000'"); assertThat(result.getQuery().toString()).isEqualTo("contactDetails.address.postCode:{0000 TO *]"); assertThat(result.getProjections()).containsOnly("contactDetails.email"); } @Test public void testBeAbleToJoinOnCollectionOfEmbeddedWithEmbeddedAndUseLikeOperator() { LuceneQueryParsingResult<Class<?>> parsingResult = parseAndTransform("select d.email from org.infinispan.query.dsl.embedded.impl.model.Employee e JOIN e.contactDetails d WHERE d.address.postCode LIKE 'EA1%'"); assertThat(parsingResult.getQuery().toString()).isEqualTo("contactDetails.address.postCode:EA1*"); assertThat(parsingResult.getProjections()).containsOnly("contactDetails.email"); } @Test public void testBeAbleToProjectUnqualifiedField() { LuceneQueryParsingResult<Class<?>> result = parseAndTransform("SELECT name, text FROM org.infinispan.query.dsl.embedded.impl.model.Employee e JOIN e.contactDetails d"); assertThat(result.getQuery().toString()).isEqualTo("*:*"); assertThat(result.getProjections()).containsOnly("name", "text"); } @Test public void testBeAbleToProjectUnqualifiedFieldAndQualifiedField() { LuceneQueryParsingResult<Class<?>> result = parseAndTransform("SELECT name, text, d.email FROM org.infinispan.query.dsl.embedded.impl.model.Employee e JOIN e.contactDetails d"); assertThat(result.getQuery().toString()).isEqualTo("*:*"); assertThat(result.getProjections()).containsOnly("name", "text", "contactDetails.email"); } @Test public void testBeAbleToProjectQualifiedField() { LuceneQueryParsingResult<Class<?>> result = parseAndTransform("SELECT e.name, e.text, d.email FROM org.infinispan.query.dsl.embedded.impl.model.Employee e JOIN e.contactDetails d"); assertThat(result.getQuery().toString()).isEqualTo("*:*"); assertThat(result.getProjections()).containsOnly("name", "text", "contactDetails.email"); } @Test public void testBeAbleToJoinOnCollectionOfEmbeddedWithTwoEmbeddedCollections() { LuceneQueryParsingResult<Class<?>> result = parseAndTransform( " SELECT d.email " + " FROM org.infinispan.query.dsl.embedded.impl.model.Employee e " + " JOIN e.contactDetails d " + " JOIN e.alternativeContactDetails a" + " WHERE d.address.postCode='EA123' AND a.email='ninja647@mailinator.com'"); assertThat(result.getQuery().toString()).isEqualTo("+contactDetails.address.postCode:EA123 +alternativeContactDetails.email:ninja647@mailinator.com"); assertThat(result.getProjections()).containsOnly("contactDetails.email"); } private void assertGeneratedLuceneQuery(String queryString, String expectedLuceneQuery) { assertGeneratedLuceneQuery(queryString, null, expectedLuceneQuery); } private void assertGeneratedLuceneQuery(String queryString, Map<String, Object> namedParameters, String expectedLuceneQuery) { LuceneQueryParsingResult<Class<?>> result = parseAndTransform(queryString, namedParameters); assertThat(result.getQuery().toString()).isEqualTo(expectedLuceneQuery); } private LuceneQueryParsingResult<Class<?>> parseAndTransform(String queryString) { return parseAndTransform(queryString, null); } private LuceneQueryParsingResult<Class<?>> parseAndTransform(String queryString, Map<String, Object> namedParameters) { ExtendedSearchIntegrator searchFactory = factoryHolder.getSearchFactory(); HibernateSearchPropertyHelper propertyHelper = new HibernateSearchPropertyHelper(searchFactory, new ReflectionEntityNamesResolver(null)); IckleParsingResult<Class<?>> ickleParsingResult = IckleParser.parse(queryString, propertyHelper); LuceneQueryMaker<Class<?>> luceneQueryMaker = new LuceneQueryMaker<>(searchFactory, propertyHelper.getDefaultFieldBridgeProvider()); return luceneQueryMaker.transform(ickleParsingResult, namedParameters, ickleParsingResult.getTargetEntityMetadata()); } }