diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/internal/tools/query/Parameters.java b/hibernate-envers/src/main/java/org/hibernate/envers/internal/tools/query/Parameters.java index 18caf91982..6e28d4e789 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/internal/tools/query/Parameters.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/internal/tools/query/Parameters.java @@ -180,6 +180,21 @@ public class Parameters { expressions.add( expression.toString() ); } + + public void addWhereWithFunction(String left, String leftFunction, String op, Object paramValue){ + final String paramName = generateQueryParam(); + localQueryParamValues.put( paramName, paramValue ); + + final StringBuilder expression = new StringBuilder(); + + expression.append( leftFunction ).append( "(" ); + expression.append( alias ).append( "." ); + expression.append( left ).append( ")" ); + expression.append( " " ).append( op ).append( " " ); + expression.append( ":" ).append( paramName ); + + expressions.add( expression.toString() ); + } public void addWhereWithParam(String left, String op, Object paramValue) { addWhereWithParam( left, true, op, paramValue ); diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/query/criteria/AuditProperty.java b/hibernate-envers/src/main/java/org/hibernate/envers/query/criteria/AuditProperty.java index 5e0f05be36..4a6c7d5d0d 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/query/criteria/AuditProperty.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/query/criteria/AuditProperty.java @@ -29,6 +29,7 @@ import org.hibernate.criterion.MatchMode; import org.hibernate.envers.configuration.spi.AuditConfiguration; import org.hibernate.envers.internal.tools.Triple; import org.hibernate.envers.query.criteria.internal.BetweenAuditExpression; +import org.hibernate.envers.query.criteria.internal.IlikeAuditExpression; import org.hibernate.envers.query.criteria.internal.InAuditExpression; import org.hibernate.envers.query.criteria.internal.NotNullAuditExpression; import org.hibernate.envers.query.criteria.internal.NullAuditExpression; @@ -91,6 +92,20 @@ public class AuditProperty implements AuditProjection { return new SimpleAuditExpression( propertyNameGetter, matchMode.toMatchString( value ), " like " ); } + /** + * Apply an "ilike" constraint + */ + public AuditCriterion ilike(T value) { + return new IlikeAuditExpression(propertyNameGetter, value.toString()); + } + + /** + * Apply an "ilike" constraint + */ + public AuditCriterion ilike(String value, MatchMode matchMode) { + return new IlikeAuditExpression( propertyNameGetter, matchMode.toMatchString( value )); + } + /** * Apply a "greater than" constraint */ diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/query/criteria/internal/IlikeAuditExpression.java b/hibernate-envers/src/main/java/org/hibernate/envers/query/criteria/internal/IlikeAuditExpression.java new file mode 100644 index 0000000000..a2647a6132 --- /dev/null +++ b/hibernate-envers/src/main/java/org/hibernate/envers/query/criteria/internal/IlikeAuditExpression.java @@ -0,0 +1,34 @@ +package org.hibernate.envers.query.criteria.internal; + +import org.hibernate.envers.configuration.spi.AuditConfiguration; +import org.hibernate.envers.internal.reader.AuditReaderImplementor; +import org.hibernate.envers.internal.tools.query.Parameters; +import org.hibernate.envers.internal.tools.query.QueryBuilder; +import org.hibernate.envers.query.criteria.AuditCriterion; +import org.hibernate.envers.query.internal.property.PropertyNameGetter; + +public class IlikeAuditExpression implements AuditCriterion { + + private PropertyNameGetter propertyNameGetter; + private String value; + + public IlikeAuditExpression(PropertyNameGetter propertyNameGetter, String value) { + this.propertyNameGetter = propertyNameGetter; + this.value = value; + } + + public void addToQuery(AuditConfiguration auditCfg, + AuditReaderImplementor versionsReader, String entityName, + QueryBuilder qb, Parameters parameters) { + + String propertyName = CriteriaTools.determinePropertyName( + auditCfg, + versionsReader, + entityName, + propertyNameGetter); + CriteriaTools.checkPropertyNotARelation( auditCfg, entityName, propertyName ); + + parameters.addWhereWithFunction( propertyName, " lower ", " like ", value.toLowerCase() ); + } + +} diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/query/SimpleQuery.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/query/SimpleQuery.java index 282a58e680..e120f6e96f 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/query/SimpleQuery.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/query/SimpleQuery.java @@ -23,11 +23,13 @@ */ package org.hibernate.envers.test.integration.query; -import javax.persistence.EntityManager; import java.util.Arrays; import java.util.HashSet; import java.util.List; +import javax.persistence.EntityManager; + +import org.hibernate.criterion.MatchMode; import org.hibernate.envers.RevisionType; import org.hibernate.envers.enhanced.SequenceIdRevisionEntity; import org.hibernate.envers.query.AuditEntity; @@ -35,12 +37,10 @@ import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.entities.StrIntTestEntity; import org.hibernate.envers.test.tools.TestTools; - +import org.hibernate.testing.TestForIssue; import org.junit.Assert; import org.junit.Test; -import org.hibernate.testing.TestForIssue; - /** * @author Adam Warski (adam at warski dot org) * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) @@ -83,7 +83,7 @@ public class SimpleQuery extends BaseEnversJPAFunctionalTestCase { site1 = em.find( StrIntTestEntity.class, id1 ); site2 = em.find( StrIntTestEntity.class, id2 ); - site1.setStr1( "c" ); + site1.setStr1( "aBc" ); site2.setNumber( 20 ); em.getTransaction().commit(); @@ -174,13 +174,13 @@ public class SimpleQuery extends BaseEnversJPAFunctionalTestCase { ); assert new HashSet( ver2 ).equals( TestTools.makeSet( - new StrIntTestEntity( "c", 10, id1 ), + new StrIntTestEntity( "aBc", 10, id1 ), new StrIntTestEntity( "b", 5, id3 ) ) ); assert new HashSet( ver3 ).equals( TestTools.makeSet( - new StrIntTestEntity( "c", 10, id1 ), + new StrIntTestEntity( "aBc", 10, id1 ), new StrIntTestEntity( "a", 5, id3 ) ) ); @@ -224,7 +224,7 @@ public class SimpleQuery extends BaseEnversJPAFunctionalTestCase { assert result.size() == 2; assert result.get( 0 ).equals( new StrIntTestEntity( "a", 10, id1 ) ); - assert result.get( 1 ).equals( new StrIntTestEntity( "c", 10, id1 ) ); + assert result.get( 1 ).equals( new StrIntTestEntity( "aBc", 10, id1 ) ); } @Test @@ -237,7 +237,7 @@ public class SimpleQuery extends BaseEnversJPAFunctionalTestCase { assert result.size() == 3; assert ((Object[]) result.get( 0 ))[0].equals( new StrIntTestEntity( "a", 10, id1 ) ); - assert ((Object[]) result.get( 1 ))[0].equals( new StrIntTestEntity( "c", 10, id1 ) ); + assert ((Object[]) result.get( 1 ))[0].equals( new StrIntTestEntity( "aBc", 10, id1 ) ); assert ((Object[]) result.get( 2 ))[0].equals( new StrIntTestEntity( null, null, id1 ) ); assert ((SequenceIdRevisionEntity) ((Object[]) result.get( 0 ))[1]).getId() == 1; @@ -317,7 +317,7 @@ public class SimpleQuery extends BaseEnversJPAFunctionalTestCase { @Test public void testEntitiesChangedAtRevision() { - StrIntTestEntity site1 = new StrIntTestEntity( "c", 10, id1 ); + StrIntTestEntity site1 = new StrIntTestEntity( "aBc", 10, id1 ); StrIntTestEntity site2 = new StrIntTestEntity( "a", 20, id2 ); List result = getAuditReader().createQuery() @@ -385,4 +385,30 @@ public class SimpleQuery extends BaseEnversJPAFunctionalTestCase { Assert.assertTrue( (number >= 0 && number <= 5) || (number >= 20 && number <= 100) ); } } + + @Test + @TestForIssue(jiraKey = "HHH-8495") + public void testIlike() { + StrIntTestEntity site1 = new StrIntTestEntity( "aBc", 10, id1 ); + + StrIntTestEntity result = (StrIntTestEntity) getAuditReader().createQuery() + .forRevisionsOfEntity( StrIntTestEntity.class, true, true ) + .add( AuditEntity.property( "str1" ).ilike( "abc" ) ) + .getSingleResult(); + + Assert.assertEquals( site1, result ); + } + + @Test + @TestForIssue(jiraKey = "HHH-8495") + public void testIlikeWithMatchMode() { + StrIntTestEntity site1 = new StrIntTestEntity( "aBc", 10, id1 ); + + StrIntTestEntity result = (StrIntTestEntity) getAuditReader().createQuery() + .forRevisionsOfEntity( StrIntTestEntity.class, true, true ) + .add( AuditEntity.property( "str1" ).ilike( "BC", MatchMode.ANYWHERE ) ) + .getSingleResult(); + + Assert.assertEquals( site1, result ); + } }