Implement envers order fragment support by introducing an internal sqm function and re-enable all envers tests
This commit is contained in:
parent
04ac8b13c3
commit
65016aaf42
|
@ -1464,7 +1464,10 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
try {
|
try {
|
||||||
for ( SqmSortSpecification sortSpecification : sqmQueryPart.getOrderByClause()
|
for ( SqmSortSpecification sortSpecification : sqmQueryPart.getOrderByClause()
|
||||||
.getSortSpecifications() ) {
|
.getSortSpecifications() ) {
|
||||||
sqlQueryPart.addSortSpecification( visitSortSpecification( sortSpecification ) );
|
final SortSpecification specification = visitSortSpecification( sortSpecification );
|
||||||
|
if ( specification != null ) {
|
||||||
|
sqlQueryPart.addSortSpecification( specification );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -1777,8 +1780,12 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SortSpecification visitSortSpecification(SqmSortSpecification sortSpecification) {
|
public SortSpecification visitSortSpecification(SqmSortSpecification sortSpecification) {
|
||||||
|
final Expression expression = resolveGroupOrOrderByExpression( sortSpecification.getSortExpression() );
|
||||||
|
if ( expression == null ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return new SortSpecification(
|
return new SortSpecification(
|
||||||
resolveGroupOrOrderByExpression( sortSpecification.getSortExpression() ),
|
expression,
|
||||||
null,
|
null,
|
||||||
sortSpecification.getSortOrder(),
|
sortSpecification.getSortOrder(),
|
||||||
sortSpecification.getNullPrecedence()
|
sortSpecification.getNullPrecedence()
|
||||||
|
@ -1850,6 +1857,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
if ( fromClauseIndex.isResolved( sqmRoot ) ) {
|
if ( fromClauseIndex.isResolved( sqmRoot ) ) {
|
||||||
log.tracef( "Already resolved SqmRoot [%s] to TableGroup", sqmRoot );
|
log.tracef( "Already resolved SqmRoot [%s] to TableGroup", sqmRoot );
|
||||||
}
|
}
|
||||||
|
final QuerySpec currentQuerySpec = currentQuerySpec();
|
||||||
final TableGroup tableGroup;
|
final TableGroup tableGroup;
|
||||||
if ( sqmRoot.isCorrelated() ) {
|
if ( sqmRoot.isCorrelated() ) {
|
||||||
final SessionFactoryImplementor sessionFactory = creationContext.getSessionFactory();
|
final SessionFactoryImplementor sessionFactory = creationContext.getSessionFactory();
|
||||||
|
@ -1863,7 +1871,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
tableGroup = new CorrelatedTableGroup(
|
tableGroup = new CorrelatedTableGroup(
|
||||||
parentTableGroup,
|
parentTableGroup,
|
||||||
sqlAliasBase,
|
sqlAliasBase,
|
||||||
currentQuerySpec(),
|
currentQuerySpec,
|
||||||
predicate -> additionalRestrictions = SqlAstTreeHelper.combinePredicates(
|
predicate -> additionalRestrictions = SqlAstTreeHelper.combinePredicates(
|
||||||
additionalRestrictions,
|
additionalRestrictions,
|
||||||
predicate
|
predicate
|
||||||
|
@ -1955,12 +1963,20 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
this,
|
this,
|
||||||
creationContext
|
creationContext
|
||||||
);
|
);
|
||||||
|
final FilterPredicate filterPredicate = FilterHelper.createFilterPredicate(
|
||||||
|
getLoadQueryInfluencers(),
|
||||||
|
(Joinable) entityDescriptor,
|
||||||
|
tableGroup
|
||||||
|
);
|
||||||
|
if ( filterPredicate != null ) {
|
||||||
|
currentQuerySpec.applyPredicate( filterPredicate );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.tracef( "Resolved SqmRoot [%s] to new TableGroup [%s]", sqmRoot, tableGroup );
|
log.tracef( "Resolved SqmRoot [%s] to new TableGroup [%s]", sqmRoot, tableGroup );
|
||||||
|
|
||||||
fromClauseIndex.register( sqmRoot, tableGroup );
|
fromClauseIndex.register( sqmRoot, tableGroup );
|
||||||
currentQuerySpec().getFromClause().addRoot( tableGroup );
|
currentQuerySpec.getFromClause().addRoot( tableGroup );
|
||||||
|
|
||||||
consumeReusablePaths( sqmRoot, tableGroup );
|
consumeReusablePaths( sqmRoot, tableGroup );
|
||||||
consumeExplicitJoins( sqmRoot, tableGroup );
|
consumeExplicitJoins( sqmRoot, tableGroup );
|
||||||
|
|
|
@ -38,6 +38,10 @@ public class FromClauseIndex extends SimpleFromClauseAccessImpl {
|
||||||
super( parent );
|
super( parent );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TableGroup findTableGroup(String alias) {
|
||||||
|
return tableGroupByAliasXref.get( alias );
|
||||||
|
}
|
||||||
|
|
||||||
public void register(SqmPath<?> sqmPath, TableGroup tableGroup) {
|
public void register(SqmPath<?> sqmPath, TableGroup tableGroup) {
|
||||||
register( sqmPath, tableGroup, null );
|
register( sqmPath, tableGroup, null );
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,10 @@ dependencies {
|
||||||
testImplementation project( ':hibernate-testing' )
|
testImplementation project( ':hibernate-testing' )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test {
|
||||||
|
include '**/**'
|
||||||
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
test {
|
test {
|
||||||
ext {
|
ext {
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.envers.boot.internal;
|
||||||
|
|
||||||
|
import org.hibernate.boot.model.FunctionContributor;
|
||||||
|
import org.hibernate.boot.model.TypeContributions;
|
||||||
|
import org.hibernate.boot.model.TypeContributor;
|
||||||
|
import org.hibernate.envers.function.OrderByFragmentFunction;
|
||||||
|
import org.hibernate.envers.internal.entities.RevisionTypeType;
|
||||||
|
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
|
||||||
|
import org.hibernate.service.ServiceRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Envers specific FunctionContributor
|
||||||
|
*
|
||||||
|
* @author Christian Beikov
|
||||||
|
*/
|
||||||
|
public class FunctionContributorImpl implements FunctionContributor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contributeFunctions(SqmFunctionRegistry functionRegistry, ServiceRegistry serviceRegistry) {
|
||||||
|
final EnversService enversService = serviceRegistry.getService( EnversService.class );
|
||||||
|
if ( !enversService.isEnabled() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
functionRegistry.register( OrderByFragmentFunction.FUNCTION_NAME, OrderByFragmentFunction.INSTANCE );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -243,7 +243,9 @@ public final class CollectionMetadataGenerator {
|
||||||
isEmbeddableElementType(),
|
isEmbeddableElementType(),
|
||||||
mappedBy,
|
mappedBy,
|
||||||
isMappedByKey( propertyValue, mappedBy ),
|
isMappedByKey( propertyValue, mappedBy ),
|
||||||
propertyValue.getOrderBy()
|
propertyValue.getOrderBy() == null
|
||||||
|
? null
|
||||||
|
: propertyValue.getRole()
|
||||||
);
|
);
|
||||||
|
|
||||||
// Creating common mapper data.
|
// Creating common mapper data.
|
||||||
|
@ -461,6 +463,9 @@ public final class CollectionMetadataGenerator {
|
||||||
// Creating a query generator builder, to which additional id data will be added, in case this collection
|
// Creating a query generator builder, to which additional id data will be added, in case this collection
|
||||||
// references some entities (either from the element or index). At the end, this will be used to build
|
// references some entities (either from the element or index). At the end, this will be used to build
|
||||||
// a query generator to read the raw data collection from the middle table.
|
// a query generator to read the raw data collection from the middle table.
|
||||||
|
final String orderBy = propertyValue.getOrderBy() == null
|
||||||
|
? propertyValue.getManyToManyOrdering()
|
||||||
|
: propertyValue.getOrderBy();
|
||||||
final QueryGeneratorBuilder queryGeneratorBuilder = new QueryGeneratorBuilder(
|
final QueryGeneratorBuilder queryGeneratorBuilder = new QueryGeneratorBuilder(
|
||||||
mainGenerator.getGlobalCfg(),
|
mainGenerator.getGlobalCfg(),
|
||||||
mainGenerator.getVerEntCfg(),
|
mainGenerator.getVerEntCfg(),
|
||||||
|
@ -468,9 +473,9 @@ public final class CollectionMetadataGenerator {
|
||||||
referencingIdData,
|
referencingIdData,
|
||||||
auditMiddleEntityName,
|
auditMiddleEntityName,
|
||||||
isRevisionTypeInId(),
|
isRevisionTypeInId(),
|
||||||
propertyValue.getOrderBy() == null
|
orderBy == null
|
||||||
? propertyValue.getManyToManyOrdering()
|
? null
|
||||||
: propertyValue.getOrderBy()
|
: propertyValue.getRole()
|
||||||
);
|
);
|
||||||
|
|
||||||
// Adding the XML mapping for the referencing entity, if the relation isn't inverse.
|
// Adding the XML mapping for the referencing entity, if the relation isn't inverse.
|
||||||
|
|
|
@ -36,7 +36,7 @@ public final class QueryGeneratorBuilder {
|
||||||
private final String auditMiddleEntityName;
|
private final String auditMiddleEntityName;
|
||||||
private final List<MiddleIdData> idDatas;
|
private final List<MiddleIdData> idDatas;
|
||||||
private final boolean revisionTypeInId;
|
private final boolean revisionTypeInId;
|
||||||
private final String orderBy;
|
private final String orderByCollectionRole;
|
||||||
|
|
||||||
QueryGeneratorBuilder(
|
QueryGeneratorBuilder(
|
||||||
GlobalConfiguration globalCfg,
|
GlobalConfiguration globalCfg,
|
||||||
|
@ -45,13 +45,13 @@ public final class QueryGeneratorBuilder {
|
||||||
MiddleIdData referencingIdData,
|
MiddleIdData referencingIdData,
|
||||||
String auditMiddleEntityName,
|
String auditMiddleEntityName,
|
||||||
boolean revisionTypeInId,
|
boolean revisionTypeInId,
|
||||||
String orderBy) {
|
String orderByCollectionRole) {
|
||||||
this.globalCfg = globalCfg;
|
this.globalCfg = globalCfg;
|
||||||
this.verEntCfg = verEntCfg;
|
this.verEntCfg = verEntCfg;
|
||||||
this.auditStrategy = auditStrategy;
|
this.auditStrategy = auditStrategy;
|
||||||
this.referencingIdData = referencingIdData;
|
this.referencingIdData = referencingIdData;
|
||||||
this.auditMiddleEntityName = auditMiddleEntityName;
|
this.auditMiddleEntityName = auditMiddleEntityName;
|
||||||
this.orderBy = orderBy;
|
this.orderByCollectionRole = orderByCollectionRole;
|
||||||
this.revisionTypeInId = revisionTypeInId;
|
this.revisionTypeInId = revisionTypeInId;
|
||||||
|
|
||||||
idDatas = new ArrayList<>();
|
idDatas = new ArrayList<>();
|
||||||
|
@ -72,13 +72,13 @@ public final class QueryGeneratorBuilder {
|
||||||
if ( idDatas.get( 0 ).isAudited() ) {
|
if ( idDatas.get( 0 ).isAudited() ) {
|
||||||
return new TwoEntityQueryGenerator(
|
return new TwoEntityQueryGenerator(
|
||||||
globalCfg, verEntCfg, auditStrategy, auditMiddleEntityName, referencingIdData,
|
globalCfg, verEntCfg, auditStrategy, auditMiddleEntityName, referencingIdData,
|
||||||
idDatas.get( 0 ), revisionTypeInId, orderBy, componentDatas
|
idDatas.get( 0 ), revisionTypeInId, orderByCollectionRole, componentDatas
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new TwoEntityOneAuditedQueryGenerator(
|
return new TwoEntityOneAuditedQueryGenerator(
|
||||||
globalCfg, verEntCfg, auditStrategy, auditMiddleEntityName, referencingIdData,
|
globalCfg, verEntCfg, auditStrategy, auditMiddleEntityName, referencingIdData,
|
||||||
idDatas.get( 0 ), revisionTypeInId, orderBy, componentDatas
|
idDatas.get( 0 ), revisionTypeInId, orderByCollectionRole, componentDatas
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ public final class QueryGeneratorBuilder {
|
||||||
}
|
}
|
||||||
return new ThreeEntityQueryGenerator(
|
return new ThreeEntityQueryGenerator(
|
||||||
globalCfg, verEntCfg, auditStrategy, auditMiddleEntityName, referencingIdData,
|
globalCfg, verEntCfg, auditStrategy, auditMiddleEntityName, referencingIdData,
|
||||||
idDatas.get( 0 ), idDatas.get( 1 ), revisionTypeInId, orderBy, componentDatas
|
idDatas.get( 0 ), idDatas.get( 1 ), revisionTypeInId, orderByCollectionRole, componentDatas
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -0,0 +1,211 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.hibernate.envers.function;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
|
import org.hibernate.metamodel.mapping.ModelPartContainer;
|
||||||
|
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||||
|
import org.hibernate.metamodel.mapping.ordering.OrderByFragment;
|
||||||
|
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||||
|
import org.hibernate.persister.collection.QueryableCollection;
|
||||||
|
import org.hibernate.persister.entity.Joinable;
|
||||||
|
import org.hibernate.query.NavigablePath;
|
||||||
|
import org.hibernate.query.spi.QueryEngine;
|
||||||
|
import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor;
|
||||||
|
import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
|
||||||
|
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
|
||||||
|
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||||
|
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
|
||||||
|
import org.hibernate.query.sqm.sql.FromClauseIndex;
|
||||||
|
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||||
|
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlAstQueryPartProcessingState;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableReferenceJoin;
|
||||||
|
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Envers specific FunctionContributor
|
||||||
|
*
|
||||||
|
* @author Christian Beikov
|
||||||
|
*/
|
||||||
|
public class OrderByFragmentFunction extends AbstractSqmFunctionDescriptor {
|
||||||
|
|
||||||
|
public static final String FUNCTION_NAME = "_order_by_frag";
|
||||||
|
public static final OrderByFragmentFunction INSTANCE = new OrderByFragmentFunction();
|
||||||
|
|
||||||
|
public OrderByFragmentFunction() {
|
||||||
|
super(
|
||||||
|
FUNCTION_NAME,
|
||||||
|
StandardArgumentsValidators.exactly( 2 ),
|
||||||
|
StandardFunctionReturnTypeResolvers.useArgType( 1 )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected <T> SelfRenderingSqmFunction<T> generateSqmFunctionExpression(
|
||||||
|
List<? extends SqmTypedNode<?>> arguments,
|
||||||
|
AllowableFunctionReturnType<T> impliedResultType,
|
||||||
|
QueryEngine queryEngine,
|
||||||
|
TypeConfiguration typeConfiguration) {
|
||||||
|
return new SelfRenderingSqmFunction<T>(
|
||||||
|
this,
|
||||||
|
null,
|
||||||
|
arguments,
|
||||||
|
impliedResultType,
|
||||||
|
getReturnTypeResolver(),
|
||||||
|
queryEngine.getCriteriaBuilder(),
|
||||||
|
getName()
|
||||||
|
) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SelfRenderingFunctionSqlAstExpression convertToSqlAst(SqmToSqlAstConverter walker) {
|
||||||
|
final AllowableFunctionReturnType<?> resultType = resolveResultType(
|
||||||
|
walker.getCreationContext().getDomainModel().getTypeConfiguration()
|
||||||
|
);
|
||||||
|
final String sqmAlias = ( (SqmLiteral<String>) getArguments().get( 0 ) ).getLiteralValue();
|
||||||
|
final String attributeRole = ( (SqmLiteral<String>) getArguments().get( 1 ) ).getLiteralValue();
|
||||||
|
final TableGroup tableGroup = ( (FromClauseIndex) walker.getFromClauseAccess() ).findTableGroup(
|
||||||
|
sqmAlias
|
||||||
|
);
|
||||||
|
final QueryableCollection collectionDescriptor = (QueryableCollection) walker.getCreationContext()
|
||||||
|
.getDomainModel()
|
||||||
|
.findCollectionDescriptor( attributeRole );
|
||||||
|
final PluralAttributeMapping pluralAttribute = collectionDescriptor.getAttributeMapping();
|
||||||
|
final QuerySpec queryPart = (QuerySpec) ( (SqlAstQueryPartProcessingState) walker.getCurrentProcessingState() ).getInflightQueryPart();
|
||||||
|
final OrderByFragment fragment;
|
||||||
|
if ( pluralAttribute.getOrderByFragment() != null ) {
|
||||||
|
fragment = pluralAttribute.getOrderByFragment();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fragment = pluralAttribute.getManyToManyOrderByFragment();
|
||||||
|
}
|
||||||
|
final String targetTableExpression;
|
||||||
|
if ( collectionDescriptor.getElementPersister() == null ) {
|
||||||
|
targetTableExpression = collectionDescriptor.getTableName();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
targetTableExpression = ( (Joinable) collectionDescriptor.getElementPersister() ).getTableName();
|
||||||
|
}
|
||||||
|
// We apply the fragment here and return null to signal that this is a no-op
|
||||||
|
fragment.apply(
|
||||||
|
queryPart,
|
||||||
|
new AuditingTableGroup( tableGroup, targetTableExpression ),
|
||||||
|
walker
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class AuditingTableGroup implements TableGroup {
|
||||||
|
|
||||||
|
private final TableGroup delegate;
|
||||||
|
private final String auditTableExpression;
|
||||||
|
private final String normalTableExpression;
|
||||||
|
|
||||||
|
public AuditingTableGroup(TableGroup delegate, String normalTableExpression) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
this.auditTableExpression = delegate.getPrimaryTableReference().getTableExpression();
|
||||||
|
this.normalTableExpression = normalTableExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelPart getExpressionType() {
|
||||||
|
return delegate.getExpressionType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TableReference resolveTableReference(
|
||||||
|
NavigablePath navigablePath,
|
||||||
|
String tableExpression,
|
||||||
|
boolean allowFkOptimization) {
|
||||||
|
if ( tableExpression.equals( normalTableExpression ) ) {
|
||||||
|
tableExpression = auditTableExpression;
|
||||||
|
}
|
||||||
|
return delegate.resolveTableReference( navigablePath, tableExpression, allowFkOptimization );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TableReference getTableReference(
|
||||||
|
NavigablePath navigablePath,
|
||||||
|
String tableExpression,
|
||||||
|
boolean allowFkOptimization) {
|
||||||
|
if ( tableExpression.equals( normalTableExpression ) ) {
|
||||||
|
tableExpression = auditTableExpression;
|
||||||
|
}
|
||||||
|
return delegate.getTableReference( navigablePath, tableExpression, allowFkOptimization );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NavigablePath getNavigablePath() {
|
||||||
|
return delegate.getNavigablePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getGroupAlias() {
|
||||||
|
return delegate.getGroupAlias();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelPartContainer getModelPart() {
|
||||||
|
return delegate.getModelPart();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSourceAlias() {
|
||||||
|
return delegate.getSourceAlias();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<TableGroupJoin> getTableGroupJoins() {
|
||||||
|
return delegate.getTableGroupJoins();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canUseInnerJoins() {
|
||||||
|
return delegate.canUseInnerJoins();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasTableGroupJoins() {
|
||||||
|
return delegate.hasTableGroupJoins();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addTableGroupJoin(TableGroupJoin join) {
|
||||||
|
delegate.addTableGroupJoin( join );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
||||||
|
delegate.visitTableGroupJoins( consumer );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyAffectedTableNames(Consumer<String> nameCollector) {
|
||||||
|
delegate.applyAffectedTableNames( nameCollector );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TableReference getPrimaryTableReference() {
|
||||||
|
return delegate.getPrimaryTableReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<TableReferenceJoin> getTableReferenceJoins() {
|
||||||
|
return delegate.getTableReferenceJoins();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -40,7 +40,7 @@ public abstract class AbstractRelationQueryGenerator implements RelationQueryGen
|
||||||
protected final MiddleIdData referencingIdData;
|
protected final MiddleIdData referencingIdData;
|
||||||
protected final boolean revisionTypeInId;
|
protected final boolean revisionTypeInId;
|
||||||
protected final String entityName;
|
protected final String entityName;
|
||||||
protected final String orderBy;
|
protected final String orderByCollectionRole;
|
||||||
|
|
||||||
private String queryString;
|
private String queryString;
|
||||||
private String queryRemovedString;
|
private String queryRemovedString;
|
||||||
|
@ -52,14 +52,14 @@ public abstract class AbstractRelationQueryGenerator implements RelationQueryGen
|
||||||
String entityName,
|
String entityName,
|
||||||
MiddleIdData referencingIdData,
|
MiddleIdData referencingIdData,
|
||||||
boolean revisionTypeInId,
|
boolean revisionTypeInId,
|
||||||
String orderBy) {
|
String orderByCollectionRole) {
|
||||||
this.globalCfg = globalCfg;
|
this.globalCfg = globalCfg;
|
||||||
this.verEntCfg = verEntCfg;
|
this.verEntCfg = verEntCfg;
|
||||||
this.entityName = entityName;
|
this.entityName = entityName;
|
||||||
this.auditStrategy = auditStrategy;
|
this.auditStrategy = auditStrategy;
|
||||||
this.referencingIdData = referencingIdData;
|
this.referencingIdData = referencingIdData;
|
||||||
this.revisionTypeInId = revisionTypeInId;
|
this.revisionTypeInId = revisionTypeInId;
|
||||||
this.orderBy = orderBy;
|
this.orderByCollectionRole = orderByCollectionRole;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -44,7 +44,7 @@ public final class OneAuditEntityQueryGenerator extends AbstractRelationQueryGen
|
||||||
boolean revisionTypeInId,
|
boolean revisionTypeInId,
|
||||||
String mappedBy,
|
String mappedBy,
|
||||||
boolean mappedByKey,
|
boolean mappedByKey,
|
||||||
String orderBy) {
|
String orderByCollectionRole) {
|
||||||
super(
|
super(
|
||||||
globalCfg,
|
globalCfg,
|
||||||
verEntCfg,
|
verEntCfg,
|
||||||
|
@ -52,7 +52,7 @@ public final class OneAuditEntityQueryGenerator extends AbstractRelationQueryGen
|
||||||
verEntCfg.getAuditEntityName( referencedEntityName ),
|
verEntCfg.getAuditEntityName( referencedEntityName ),
|
||||||
referencingIdData,
|
referencingIdData,
|
||||||
revisionTypeInId,
|
revisionTypeInId,
|
||||||
orderBy
|
orderByCollectionRole
|
||||||
);
|
);
|
||||||
|
|
||||||
this.mappedBy = mappedBy;
|
this.mappedBy = mappedBy;
|
||||||
|
@ -106,8 +106,8 @@ public final class OneAuditEntityQueryGenerator extends AbstractRelationQueryGen
|
||||||
}
|
}
|
||||||
|
|
||||||
// ORDER BY
|
// ORDER BY
|
||||||
if ( !StringHelper.isEmpty( orderBy ) ) {
|
if ( !StringHelper.isEmpty( orderByCollectionRole ) ) {
|
||||||
qb.addOrderFragment( REFERENCED_ENTITY_ALIAS, orderBy );
|
qb.addOrderFragment( REFERENCED_ENTITY_ALIAS, orderByCollectionRole );
|
||||||
}
|
}
|
||||||
|
|
||||||
return qb;
|
return qb;
|
||||||
|
|
|
@ -45,7 +45,7 @@ public final class ThreeEntityQueryGenerator extends AbstractRelationQueryGenera
|
||||||
MiddleIdData referencedIdData,
|
MiddleIdData referencedIdData,
|
||||||
MiddleIdData indexIdData,
|
MiddleIdData indexIdData,
|
||||||
boolean revisionTypeInId,
|
boolean revisionTypeInId,
|
||||||
String orderBy,
|
String orderByCollectionRole,
|
||||||
MiddleComponentData... componentData) {
|
MiddleComponentData... componentData) {
|
||||||
super(
|
super(
|
||||||
globalCfg,
|
globalCfg,
|
||||||
|
@ -54,7 +54,7 @@ public final class ThreeEntityQueryGenerator extends AbstractRelationQueryGenera
|
||||||
versionsMiddleEntityName,
|
versionsMiddleEntityName,
|
||||||
referencingIdData,
|
referencingIdData,
|
||||||
revisionTypeInId,
|
revisionTypeInId,
|
||||||
orderBy
|
orderByCollectionRole
|
||||||
);
|
);
|
||||||
|
|
||||||
this.referencedIdData = referencedIdData;
|
this.referencedIdData = referencedIdData;
|
||||||
|
@ -139,8 +139,8 @@ public final class ThreeEntityQueryGenerator extends AbstractRelationQueryGenera
|
||||||
// ORDER BY
|
// ORDER BY
|
||||||
// Hibernate applies @OrderBy on map elements, not the key.
|
// Hibernate applies @OrderBy on map elements, not the key.
|
||||||
// So here we apply it to the referenced entity, not the actual index entity that represents the key.
|
// So here we apply it to the referenced entity, not the actual index entity that represents the key.
|
||||||
if ( !StringHelper.isEmpty( orderBy ) ) {
|
if ( !StringHelper.isEmpty( orderByCollectionRole ) ) {
|
||||||
qb.addOrderFragment( REFERENCED_ENTITY_ALIAS, orderBy );
|
qb.addOrderFragment( REFERENCED_ENTITY_ALIAS, orderByCollectionRole );
|
||||||
}
|
}
|
||||||
return qb;
|
return qb;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ public final class TwoEntityOneAuditedQueryGenerator extends AbstractRelationQue
|
||||||
MiddleIdData referencingIdData,
|
MiddleIdData referencingIdData,
|
||||||
MiddleIdData referencedIdData,
|
MiddleIdData referencedIdData,
|
||||||
boolean revisionTypeInId,
|
boolean revisionTypeInId,
|
||||||
String orderBy,
|
String orderorderByCollectionRoley,
|
||||||
MiddleComponentData... componentData) {
|
MiddleComponentData... componentData) {
|
||||||
super(
|
super(
|
||||||
globalCfg,
|
globalCfg,
|
||||||
|
@ -49,7 +49,7 @@ public final class TwoEntityOneAuditedQueryGenerator extends AbstractRelationQue
|
||||||
versionsMiddleEntityName,
|
versionsMiddleEntityName,
|
||||||
referencingIdData,
|
referencingIdData,
|
||||||
revisionTypeInId,
|
revisionTypeInId,
|
||||||
orderBy
|
orderorderByCollectionRoley
|
||||||
);
|
);
|
||||||
|
|
||||||
this.referencedIdData = referencedIdData;
|
this.referencedIdData = referencedIdData;
|
||||||
|
@ -96,8 +96,8 @@ public final class TwoEntityOneAuditedQueryGenerator extends AbstractRelationQue
|
||||||
// ee.originalId.id_ref_ing = :id_ref_ing
|
// ee.originalId.id_ref_ing = :id_ref_ing
|
||||||
referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery( rootParameters, originalIdPropertyName, true );
|
referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery( rootParameters, originalIdPropertyName, true );
|
||||||
// ORDER BY
|
// ORDER BY
|
||||||
if ( !StringHelper.isEmpty( orderBy ) ) {
|
if ( !StringHelper.isEmpty( orderByCollectionRole ) ) {
|
||||||
qb.addOrderFragment( REFERENCED_ENTITY_ALIAS, orderBy );
|
qb.addOrderFragment( REFERENCED_ENTITY_ALIAS, orderByCollectionRole );
|
||||||
}
|
}
|
||||||
return qb;
|
return qb;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
package org.hibernate.envers.internal.entities.mapper.relation.query;
|
package org.hibernate.envers.internal.entities.mapper.relation.query;
|
||||||
|
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
|
||||||
import org.hibernate.envers.configuration.internal.AuditEntitiesConfiguration;
|
import org.hibernate.envers.configuration.internal.AuditEntitiesConfiguration;
|
||||||
import org.hibernate.envers.configuration.internal.GlobalConfiguration;
|
import org.hibernate.envers.configuration.internal.GlobalConfiguration;
|
||||||
import org.hibernate.envers.internal.entities.mapper.relation.MiddleComponentData;
|
import org.hibernate.envers.internal.entities.mapper.relation.MiddleComponentData;
|
||||||
|
@ -42,7 +41,7 @@ public final class TwoEntityQueryGenerator extends AbstractRelationQueryGenerato
|
||||||
MiddleIdData referencingIdData,
|
MiddleIdData referencingIdData,
|
||||||
MiddleIdData referencedIdData,
|
MiddleIdData referencedIdData,
|
||||||
boolean revisionTypeInId,
|
boolean revisionTypeInId,
|
||||||
String orderBy,
|
String orderByCollectionRole,
|
||||||
MiddleComponentData... componentData) {
|
MiddleComponentData... componentData) {
|
||||||
super(
|
super(
|
||||||
globalCfg,
|
globalCfg,
|
||||||
|
@ -51,7 +50,7 @@ public final class TwoEntityQueryGenerator extends AbstractRelationQueryGenerato
|
||||||
versionsMiddleEntityName,
|
versionsMiddleEntityName,
|
||||||
referencingIdData,
|
referencingIdData,
|
||||||
revisionTypeInId,
|
revisionTypeInId,
|
||||||
orderBy
|
orderByCollectionRole
|
||||||
);
|
);
|
||||||
|
|
||||||
this.referencedIdData = referencedIdData;
|
this.referencedIdData = referencedIdData;
|
||||||
|
@ -109,8 +108,8 @@ public final class TwoEntityQueryGenerator extends AbstractRelationQueryGenerato
|
||||||
referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery( rootParameters, originalIdPropertyName, true );
|
referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery( rootParameters, originalIdPropertyName, true );
|
||||||
|
|
||||||
// ORDER BY
|
// ORDER BY
|
||||||
if ( !StringHelper.isEmpty( orderBy ) ) {
|
if ( !StringHelper.isEmpty( orderByCollectionRole ) ) {
|
||||||
qb.addOrderFragment( REFERENCED_ENTITY_ALIAS, orderBy );
|
qb.addOrderFragment( REFERENCED_ENTITY_ALIAS, orderByCollectionRole );
|
||||||
}
|
}
|
||||||
|
|
||||||
return qb;
|
return qb;
|
||||||
|
|
|
@ -8,21 +8,23 @@ package org.hibernate.envers.internal.tools.query;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.persistence.criteria.JoinType;
|
import javax.persistence.criteria.JoinType;
|
||||||
|
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.envers.RevisionType;
|
import org.hibernate.envers.RevisionType;
|
||||||
|
import org.hibernate.envers.function.OrderByFragmentFunction;
|
||||||
import org.hibernate.envers.internal.entities.RevisionTypeType;
|
import org.hibernate.envers.internal.entities.RevisionTypeType;
|
||||||
import org.hibernate.envers.internal.tools.MutableInteger;
|
import org.hibernate.envers.internal.tools.MutableInteger;
|
||||||
import org.hibernate.envers.internal.tools.StringTools;
|
import org.hibernate.envers.internal.tools.StringTools;
|
||||||
import org.hibernate.envers.internal.tools.Triple;
|
import org.hibernate.envers.internal.tools.Triple;
|
||||||
import org.hibernate.envers.tools.Pair;
|
import org.hibernate.envers.tools.Pair;
|
||||||
import org.hibernate.query.Query;
|
import org.hibernate.query.Query;
|
||||||
|
import org.hibernate.query.internal.QueryLiteralHelper;
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -186,8 +188,8 @@ public class QueryBuilder {
|
||||||
orders.add( Triple.make( alias, propertyName, ascending ) );
|
orders.add( Triple.make( alias, propertyName, ascending ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addOrderFragment(String alias, String fragment) {
|
public void addOrderFragment(String alias, String orderByCollectionRole) {
|
||||||
orderFragments.add( Pair.make( alias, fragment ) );
|
orderFragments.add( Pair.make( alias, orderByCollectionRole ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addProjection(String function, String alias, String propertyName, boolean distinct) {
|
public void addProjection(String function, String alias, String propertyName, boolean distinct) {
|
||||||
|
@ -247,47 +249,25 @@ public class QueryBuilder {
|
||||||
StringTools.append( sb, getOrderList().iterator(), ", " );
|
StringTools.append( sb, getOrderList().iterator(), ", " );
|
||||||
}
|
}
|
||||||
else if ( !orderFragments.isEmpty() ) {
|
else if ( !orderFragments.isEmpty() ) {
|
||||||
// todo (6.0) : How to backport HHH-12992 to use Template#translateOrderBy from main?
|
sb.append( " order by " );
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
|
||||||
|
|
||||||
// sb.append( " order by " );
|
final Iterator<Pair<String, String>> fragmentIterator = orderFragments.iterator();
|
||||||
//
|
while( fragmentIterator.hasNext() ) {
|
||||||
// final Iterator<Pair<String, String>> fragmentIterator = orderFragments.iterator();
|
final Pair<String, String> fragment = fragmentIterator.next();
|
||||||
// while( fragmentIterator.hasNext() ) {
|
sb.append( OrderByFragmentFunction.FUNCTION_NAME ).append( '(' );
|
||||||
// final Pair<String, String> fragment = fragmentIterator.next();
|
// The first argument is the sqm alias of the from node
|
||||||
// final OrderByTranslation orderByFragmentTranslation = Template.translateOrderBy(
|
QueryLiteralHelper.appendStringLiteral( sb, fragment.getFirst() );
|
||||||
// fragment.getSecond(),
|
sb.append( ", " );
|
||||||
// new ColumnMapper() {
|
// The second argument is the collection role that contains the order by fragment
|
||||||
// @Override
|
QueryLiteralHelper.appendStringLiteral( sb, fragment.getSecond() );
|
||||||
// public SqlValueReference[] map(String reference) throws HibernateException {
|
sb.append( ')' );
|
||||||
// return new SqlValueReference[ 0 ];
|
if ( fragmentIterator.hasNext() ) {
|
||||||
// }
|
sb.append( ", " );
|
||||||
// },
|
}
|
||||||
// sessionFactory,
|
}
|
||||||
// sessionFactory.getJdbcServices().getDialect(),
|
|
||||||
// sessionFactory.getSqlFunctionRegistry()
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// sb.append( orderByFragmentTranslation.injectAliases( new QueryOrderByAliasResolver( fragment.getFirst() ) ) );
|
|
||||||
// if ( fragmentIterator.hasNext() ) {
|
|
||||||
// sb.append( ", " );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// private class QueryOrderByAliasResolver implements OrderByAliasResolver {
|
|
||||||
// private String alias;
|
|
||||||
// public QueryOrderByAliasResolver(String alias) {
|
|
||||||
// this.alias = alias;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public String resolveTableAlias(String columnReference) {
|
|
||||||
// return alias;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
private List<String> getSelectAliasList() {
|
private List<String> getSelectAliasList() {
|
||||||
final List<String> aliasList = new ArrayList<>();
|
final List<String> aliasList = new ArrayList<>();
|
||||||
for ( JoinParameter from : froms ) {
|
for ( JoinParameter from : froms ) {
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
org.hibernate.envers.boot.internal.FunctionContributorImpl
|
|
@ -16,6 +16,9 @@
|
||||||
<bean id="typeContributor" class="org.hibernate.envers.boot.internal.TypeContributorImpl"/>
|
<bean id="typeContributor" class="org.hibernate.envers.boot.internal.TypeContributorImpl"/>
|
||||||
<service ref="typeContributor" interface="org.hibernate.boot.model.TypeContributor"/>
|
<service ref="typeContributor" interface="org.hibernate.boot.model.TypeContributor"/>
|
||||||
|
|
||||||
|
<bean id="functionContributor" class="org.hibernate.envers.boot.internal.FunctionContributorImpl"/>
|
||||||
|
<service ref="functionContributor" interface="org.hibernate.boot.model.FunctionContributor"/>
|
||||||
|
|
||||||
<bean id="serviceContributor" class="org.hibernate.envers.boot.internal.EnversServiceContributor"/>
|
<bean id="serviceContributor" class="org.hibernate.envers.boot.internal.EnversServiceContributor"/>
|
||||||
<service ref="serviceContributor" interface="org.hibernate.service.spi.ServiceContributor"/>
|
<service ref="serviceContributor" interface="org.hibernate.service.spi.ServiceContributor"/>
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ processResources {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation( project(':hibernate-core') ) { transitive = false }
|
implementation( project(':hibernate-core') ) { transitive = false }
|
||||||
implementation( libraries.jpa ) { transitive = false }
|
implementation( libraries.jpa ) { transitive = false }
|
||||||
|
implementation( libraries.jta ) { transitive = false }
|
||||||
implementation( libraries.maven_core ) { transitive = false }
|
implementation( libraries.maven_core ) { transitive = false }
|
||||||
implementation( libraries.maven_artifact ) { transitive = false }
|
implementation( libraries.maven_artifact ) { transitive = false }
|
||||||
implementation( libraries.maven_plugin ) { transitive = false }
|
implementation( libraries.maven_plugin ) { transitive = false }
|
||||||
|
|
Loading…
Reference in New Issue