Skip to content

Commit

Permalink
HHH-11452 Added possibility to apply the like operator on a function …
Browse files Browse the repository at this point in the history
…criterion. Added possibility to use the id of an entity as function argument.
  • Loading branch information
Felix Feisst authored and Naros committed Dec 16, 2021
1 parent 640bd85 commit e50037e
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -317,14 +317,28 @@ public void addWhereOrNullRestriction(String left, boolean addAliasLeft, String
* Add where clause with a function call on the left and a scalar value on the right.
*
* @param configuration the configuration.
* @param aliasToEntityNameMap alias to entity name map, never {@literal null}
* @param function the function.
* @param op the operator.
* @param value the scalar value.
*/
public void addWhereWithFunction(Configuration configuration, AuditFunction function, String op, Object value) {
public void addWhereWithFunction(
Configuration configuration,
Map<String, String> aliasToEntityNameMap,
AuditFunction function,
String op,
Object value) {
final StringBuilder expression = new StringBuilder();

QueryBuilder.appendFunctionArgument( configuration, queryParamCounter, localQueryParamValues, alias, expression, function );
QueryBuilder.appendFunctionArgument(
configuration,
aliasToEntityNameMap,
queryParamCounter,
localQueryParamValues,
alias,
expression,
function
);

expression.append( ' ' ).append( op );

Expand All @@ -339,15 +353,30 @@ public void addWhereWithFunction(Configuration configuration, AuditFunction func
* Add a where clause with a function call on the left and an optionally aliased property on the right.
*
* @param configuration the configuration.
* @param aliasToEntityNameMap alias to entity name map, never {@literal null}
* @param function the function.
* @param op the operator.
* @param aliasRight the optional alias of the right property, may be {@literal null}
* @param right the property.
*/
public void addWhereWithFunction(Configuration configuration, AuditFunction function, String op, String aliasRight, String right) {
public void addWhereWithFunction(
Configuration configuration,
Map<String, String> aliasToEntityNameMap,
AuditFunction function,
String op,
String aliasRight,
String right) {
final StringBuilder expression = new StringBuilder();

QueryBuilder.appendFunctionArgument( configuration, queryParamCounter, localQueryParamValues, alias, expression, function );
QueryBuilder.appendFunctionArgument(
configuration,
aliasToEntityNameMap,
queryParamCounter,
localQueryParamValues,
alias,
expression,
function
);

expression.append( ' ' ).append( op ).append( ' ' );

Expand All @@ -363,12 +392,19 @@ public void addWhereWithFunction(Configuration configuration, AuditFunction func
* Adds a where clause with a left (optionally aliased) property and a function call on the right side.
*
* @param configuration the configuration.
* @param aliasToEntityNameMap alias to entity name map, never {@literal null}
* @param aliasLeft the optional alias of the left property, may be {@literal null}
* @param left the property.
* @param op the operator.
* @param function the function.
*/
public void addWhereWithFunction(Configuration configuration, String aliasLeft, String left, String op, AuditFunction function) {
public void addWhereWithFunction(
Configuration configuration,
Map<String, String> aliasToEntityNameMap,
String aliasLeft,
String left,
String op,
AuditFunction function) {
final StringBuilder expression = new StringBuilder();

if ( aliasLeft != null ) {
Expand All @@ -378,7 +414,15 @@ public void addWhereWithFunction(Configuration configuration, String aliasLeft,

expression.append( ' ' ).append( op ).append( ' ' );

QueryBuilder.appendFunctionArgument( configuration, queryParamCounter, localQueryParamValues, alias, expression, function );
QueryBuilder.appendFunctionArgument(
configuration,
aliasToEntityNameMap,
queryParamCounter,
localQueryParamValues,
alias,
expression,
function
);

expressions.add( expression.toString() );
}
Expand All @@ -387,18 +431,40 @@ public void addWhereWithFunction(Configuration configuration, String aliasLeft,
* Adds a where clause with a function call on both the left and right of the predicate.
*
* @param configuration the configuration.
* @param aliasToEntityNameMap alias to entity name map, never {@literal null}
* @param left the left-side function.
* @param op the operator.
* @param right the right-side function.
*/
public void addWhereWithFunction(Configuration configuration, AuditFunction left, String op, AuditFunction right) {
public void addWhereWithFunction(
Configuration configuration,
Map<String, String> aliasToEntityNameMap,
AuditFunction left,
String op,
AuditFunction right) {
final StringBuilder expression = new StringBuilder();

QueryBuilder.appendFunctionArgument( configuration, queryParamCounter, localQueryParamValues, alias, expression, left );
QueryBuilder.appendFunctionArgument(
configuration,
aliasToEntityNameMap,
queryParamCounter,
localQueryParamValues,
alias,
expression,
left
);

expression.append( ' ' ).append( op ).append( ' ' );

QueryBuilder.appendFunctionArgument( configuration, queryParamCounter, localQueryParamValues, alias, expression, right );
QueryBuilder.appendFunctionArgument(
configuration,
aliasToEntityNameMap,
queryParamCounter,
localQueryParamValues,
alias,
expression,
right
);

expressions.add( expression.toString() );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,23 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;

import jakarta.persistence.criteria.JoinType;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.envers.RevisionType;
import org.hibernate.envers.boot.internal.EnversService;
import org.hibernate.envers.configuration.Configuration;
import org.hibernate.envers.function.OrderByFragmentFunction;
import org.hibernate.envers.internal.entities.RevisionTypeType;
import org.hibernate.envers.internal.entities.mapper.id.QueryParameterData;
import org.hibernate.envers.internal.tools.MutableInteger;
import org.hibernate.envers.internal.tools.StringTools;
import org.hibernate.envers.internal.tools.Triple;
import org.hibernate.envers.query.criteria.AuditFunction;
import org.hibernate.envers.query.criteria.AuditId;
import org.hibernate.envers.query.criteria.AuditProperty;
import org.hibernate.envers.tools.Pair;
import org.hibernate.query.Query;
Expand Down Expand Up @@ -214,14 +219,23 @@ public void addProjection(String function, String alias, String propertyName, bo
}
}

public void addProjection(Configuration configuration, AuditFunction function) {
public void addProjection(Configuration configuration, Map<String, String> aliasToEntityNameMap, AuditFunction function) {
final StringBuilder expression = new StringBuilder();
appendFunctionArgument( configuration, paramCounter, projectionQueryParamValues, alias, expression, function );
appendFunctionArgument(
configuration,
aliasToEntityNameMap,
paramCounter,
projectionQueryParamValues,
alias,
expression,
function
);
projections.add( expression.toString() );
}

protected static void appendFunctionArgument(
Configuration configuration,
Map<String, String> aliasToEntityNameMap,
MutableInteger paramCounter,
Map<String, Object> queryParamValues,
String alias,
Expand All @@ -235,11 +249,42 @@ protected static void appendFunctionArgument(
if ( !first ) {
expression.append( ',' );
}
appendFunctionArgument( configuration, paramCounter, queryParamValues, alias, expression, innerArg );
appendFunctionArgument(
configuration,
aliasToEntityNameMap,
paramCounter,
queryParamValues,
alias,
expression,
innerArg
);
first = false;
}
expression.append( ')' );
}
else if ( argument instanceof AuditId ) {
AuditId<?> id = (AuditId<?>) argument;
String prefix = configuration.getOriginalIdPropertyName();
String idAlias = id.getAlias( alias );
String entityName = aliasToEntityNameMap.get( idAlias );
/*
* Resolve the name of the id property by reusing the IdMapper.mapToQueryParametersFromId() method. Null is
* passed as value because only the name of the property is of interest. TODO: is there a better way to
* obtain the name of the id property?
*/
EnversService enversService = configuration.getEnversService();
List<QueryParameterData> parameters = enversService.getEntitiesConfigurations().get( entityName )
.getIdMapper()
.mapToQueryParametersFromId( null );
if ( parameters.size() != 1 ) {
throw new HibernateException( "Cannot add id property as function argument when id property is not a single column property" );
}
String propertyName = parameters.get( 0 ).getProperty( prefix );
if ( idAlias != null ) {
expression.append( idAlias ).append( '.' );
}
expression.append( propertyName );
}
else if ( argument instanceof AuditProperty ) {
AuditProperty<?> property = (AuditProperty<?>) argument;
String propertyAlias = property.getAlias( alias );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,20 @@ public AuditCriterion ne(Object value) {
return new SimpleFunctionAuditExpression( this, value, "<>" );
}

/**
* Apply a "like" constraint
*/
public AuditCriterion like(Object value) {
return new SimpleFunctionAuditExpression( this, value, " like " );
}

/**
* Apply a "like" constraint
*/
public AuditCriterion like(String value, MatchMode matchMode) {
return new SimpleFunctionAuditExpression( this, matchMode.toMatchString( value ), " like " );
}

/**
* Apply a "greater than" constraint
*/
Expand Down Expand Up @@ -222,9 +236,13 @@ public AuditCriterion geFunction(AuditFunction otherFunction) {
}

@Override
public void addProjectionToQuery(EnversService enversService, AuditReaderImplementor auditReader,
Map<String, String> aliasToEntityNameMap, String baseAlias, QueryBuilder queryBuilder) {
queryBuilder.addProjection( enversService.getConfig(), this );
public void addProjectionToQuery(
EnversService enversService,
AuditReaderImplementor auditReader,
Map<String, String> aliasToEntityNameMap,
String baseAlias,
QueryBuilder queryBuilder) {
queryBuilder.addProjection( enversService.getConfig(), aliasToEntityNameMap, this );
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ public void addToQuery(
String baseAlias,
QueryBuilder queryBuilder,
Parameters parameters) {
parameters.addWhereWithFunction( enversService.getConfig(), leftFunction, op, rightFunction );
parameters.addWhereWithFunction(
enversService.getConfig(),
aliasToEntityNameMap,
leftFunction,
op,
rightFunction
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ public void addToQuery(
entityName,
propertyNameGetter );
CriteriaTools.checkPropertyNotARelation( enversService, entityName, propertyName );
parameters.addWhereWithFunction( enversService.getConfig(), effectiveAlias, propertyName, op, function );
parameters.addWhereWithFunction(
enversService.getConfig(),
aliasToEntityNameMap,
effectiveAlias,
propertyName,
op,
function
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ public void addToQuery(
if ( enversService.getEntitiesConfigurations().isVersioned( otherEntityName ) ) {
CriteriaTools.checkPropertyNotARelation( enversService, otherEntityName, otherPropertyName );
}
parameters.addWhereWithFunction( enversService.getConfig(), function, op, effectiveOtherAlias, otherPropertyName );
parameters.addWhereWithFunction(
enversService.getConfig(),
aliasToEntityNameMap,
function,
op,
effectiveOtherAlias,
otherPropertyName
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,14 @@ public SimpleFunctionAuditExpression(AuditFunction function, Object value, Strin
}

@Override
public void addToQuery(EnversService enversService, AuditReaderImplementor versionsReader,
Map<String, String> aliasToEntityNameMap, String baseAlias, QueryBuilder qb, Parameters parameters) {
parameters.addWhereWithFunction( enversService.getConfig(), function, op, value );
public void addToQuery(
EnversService enversService,
AuditReaderImplementor versionsReader,
Map<String, String> aliasToEntityNameMap,
String baseAlias,
QueryBuilder qb,
Parameters parameters) {
parameters.addWhereWithFunction( enversService.getConfig(), aliasToEntityNameMap, function, op, value );
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -153,4 +153,12 @@ public void testComparisonPropertyWithFunction() {
assertEquals( "Expected the entity to be returned", testEntity1.getId(), entity.getId() );
}

@Test
public void testFunctionOnIdProperty() {
TestEntity entity = (TestEntity) getAuditReader().createQuery().forEntitiesAtRevision( TestEntity.class, 1 )
.add( AuditEntity.function( "str", AuditEntity.id() ).like( "%1%" ) ).getSingleResult();
assertNotNull( "Expected the entity to be returned", entity );
assertEquals( "Expected the entity to be returned", testEntity1.getId(), entity.getId() );
}

}

0 comments on commit e50037e

Please sign in to comment.