HHH-14977 - @Where is broken in 6.0

`@Where` and `@Filter` fragments are now fully handled as AST - each fragment gets its own Predicate instance.

Some more work coming to clean up methods we no longer use which require the old String-manip approach.
This commit is contained in:
Steve Ebersole 2021-12-15 17:52:26 -06:00
parent 4e4f2e40b4
commit 1c5ec0612c
19 changed files with 643 additions and 338 deletions

View File

@ -7,25 +7,24 @@
package org.hibernate.internal; package org.hibernate.internal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Consumer;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.hibernate.Filter; import org.hibernate.Filter;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.Joinable; import org.hibernate.persister.entity.Joinable;
import org.hibernate.sql.Template; import org.hibernate.sql.Template;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.predicate.FilterPredicate; import org.hibernate.sql.ast.tree.predicate.FilterPredicate;
import org.hibernate.sql.ast.tree.predicate.Predicate;
import org.hibernate.sql.ast.tree.select.QuerySpec;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import static org.hibernate.internal.util.StringHelper.safeInterning; import static org.hibernate.internal.util.StringHelper.safeInterning;
@ -39,12 +38,13 @@ import static org.hibernate.internal.util.StringHelper.safeInterning;
*/ */
public class FilterHelper { public class FilterHelper {
private static final Pattern FILTER_PARAMETER_PATTERN = Pattern.compile( ":(\\S+)\\.(\\w+)" ); private static final Pattern FILTER_PARAMETER_PATTERN = Pattern.compile( ":(\\S+)(\\w+)" );
private final String[] filterNames; private final String[] filterNames;
private final String[] filterConditions; private final String[] filterConditions;
private final boolean[] filterAutoAliasFlags; private final boolean[] filterAutoAliasFlags;
private final Map<String, String>[] filterAliasTableMaps; private final Map<String, String>[] filterAliasTableMaps;
private final List<String>[] parameterNames;
/** /**
* The map of defined filters. This is expected to be in format * The map of defined filters. This is expected to be in format
@ -56,10 +56,13 @@ public class FilterHelper {
*/ */
public FilterHelper(List<FilterConfiguration> filters, SessionFactoryImplementor factory) { public FilterHelper(List<FilterConfiguration> filters, SessionFactoryImplementor factory) {
int filterCount = filters.size(); int filterCount = filters.size();
filterNames = new String[filterCount]; filterNames = new String[filterCount];
filterConditions = new String[filterCount]; filterConditions = new String[filterCount];
filterAutoAliasFlags = new boolean[filterCount]; filterAutoAliasFlags = new boolean[filterCount];
filterAliasTableMaps = new Map[filterCount]; filterAliasTableMaps = new Map[filterCount];
parameterNames = new List[filterCount];
filterCount = 0; filterCount = 0;
for ( final FilterConfiguration filter : filters ) { for ( final FilterConfiguration filter : filters ) {
filterAutoAliasFlags[filterCount] = false; filterAutoAliasFlags[filterCount] = false;
@ -80,13 +83,17 @@ public class FilterHelper {
filterAutoAliasFlags[filterCount] = true; filterAutoAliasFlags[filterCount] = true;
} }
filterConditions[filterCount] = safeInterning( final Matcher matcher = FILTER_PARAMETER_PATTERN.matcher( filterConditions[filterCount] );
StringHelper.replace( String copy = filterConditions[filterCount];
filterConditions[filterCount], final List<String> filterParamNames = new ArrayList<>();
":", parameterNames[filterCount] = filterParamNames;
":" + filterNames[filterCount] + "." while( matcher.find() ) {
) final String parameterLabel = filterConditions[filterCount].substring( matcher.start() + 1, matcher.end() );
); filterParamNames.add( parameterLabel );
copy = copy.replaceAll( ":" + parameterLabel, ":" + filterNames[filterCount] + "." + parameterLabel );
}
filterConditions[filterCount] = safeInterning( copy );
filterCount++; filterCount++;
} }
} }
@ -154,113 +161,85 @@ public class FilterHelper {
} }
} }
public static FilterPredicate createFilterPredicate( public void applyFilters(
LoadQueryInfluencers loadQueryInfluencers, FilterAliasGenerator aliasGenerator,
Joinable joinable, Map<String, Filter> enabledFilters,
TableGroup rootTableGroup) { Consumer<Predicate> predicateConsumer) {
return createFilterPredicate( loadQueryInfluencers, joinable, rootTableGroup, true ); final FilterPredicate predicate = generateFilterPredicate( aliasGenerator, enabledFilters );
} if ( predicate != null ) {
predicateConsumer.accept( predicate );
public static FilterPredicate createFilterPredicate(
Map<String,Filter> enabledFilters,
Joinable joinable,
TableGroup rootTableGroup) {
return createFilterPredicate( enabledFilters, joinable, rootTableGroup, true );
}
public static FilterPredicate createFilterPredicate(
Map<String,Filter> enabledFilters,
Joinable joinable,
TableGroup rootTableGroup,
boolean useIdentificationVariable) {
final String filterFragment = joinable.filterFragment(
rootTableGroup,
enabledFilters,
Collections.emptySet(),
useIdentificationVariable
);
if ( StringHelper.isNotEmpty( filterFragment ) ) {
return doCreateFilterPredicate( filterFragment, enabledFilters );
}
else {
return null;
}
}
public static FilterPredicate createFilterPredicate(
LoadQueryInfluencers loadQueryInfluencers,
Joinable joinable,
TableGroup rootTableGroup,
boolean useIdentificationVariable) {
final String filterFragment = joinable.filterFragment(
rootTableGroup,
loadQueryInfluencers.getEnabledFilters(),
Collections.emptySet(),
useIdentificationVariable
);
if ( StringHelper.isNotEmpty( filterFragment ) ) {
return doCreateFilterPredicate( filterFragment, loadQueryInfluencers.getEnabledFilters() );
}
else {
return null;
} }
} }
public static FilterPredicate createManyToManyFilterPredicate(LoadQueryInfluencers loadQueryInfluencers, CollectionPersister collectionPersister, TableGroup tableGroup) { public void applyFilters(
assert collectionPersister.isManyToMany(); QuerySpec querySpec,
final String filterFragment = collectionPersister.getManyToManyFilterFragment( tableGroup, loadQueryInfluencers.getEnabledFilters() ); FilterAliasGenerator aliasGenerator,
if ( StringHelper.isNotEmpty( filterFragment ) ) { Map<String, Filter> enabledFilters) {
return doCreateFilterPredicate( filterFragment, loadQueryInfluencers.getEnabledFilters() ); final FilterPredicate predicate = generateFilterPredicate( aliasGenerator, enabledFilters );
} if ( predicate != null ) {
else { querySpec.applyPredicate( predicate );
return null;
} }
} }
public static FilterPredicate doCreateFilterPredicate(String filterFragment, Map<String, Filter> enabledFilters) { public FilterPredicate generateFilterPredicate(FilterAliasGenerator aliasGenerator, Map<String, Filter> enabledFilters) {
final Matcher matcher = FILTER_PARAMETER_PATTERN.matcher( filterFragment ); final FilterPredicate filterPredicate = new FilterPredicate();
final StringBuilder sb = new StringBuilder();
int pos = 0; for ( int i = 0, max = filterNames.length; i < max; i++ ) {
final List<FilterJdbcParameter> parameters = new ArrayList<>( matcher.groupCount() ); final String filterName = filterNames[i];
while( matcher.find() ) {
sb.append( filterFragment, pos, matcher.start() );
pos = matcher.end();
sb.append( "?" );
final String filterName = matcher.group( 1 );
final String parameterName = matcher.group( 2 );
final FilterImpl enabledFilter = (FilterImpl) enabledFilters.get( filterName ); final FilterImpl enabledFilter = (FilterImpl) enabledFilters.get( filterName );
if ( enabledFilter == null ) { if ( enabledFilter != null ) {
throw new MappingException( String.format( "unknown filter [%s]", filterName ) ); String condition = render( aliasGenerator, i );
}
final List<String> filterParameterNames = parameterNames[i];
for ( int paramPos = 0; paramPos < filterParameterNames.size(); paramPos++ ) {
final String parameterName = filterParameterNames.get( paramPos );
final Type parameterType = enabledFilter.getFilterDefinition().getParameterType( parameterName ); final Type parameterType = enabledFilter.getFilterDefinition().getParameterType( parameterName );
if ( ! (parameterType instanceof JdbcMapping ) ) { if ( ! (parameterType instanceof JdbcMapping) ) {
throw new MappingException( String.format( "parameter [%s] for filter [%s] is not of JdbcMapping type", parameterName, filterName ) ); throw new MappingException( String.format( "parameter [%s] for filter [%s] is not of JdbcMapping type", parameterName, filterName ) );
} }
final JdbcMapping jdbcMapping = (JdbcMapping) parameterType; final JdbcMapping jdbcMapping = (JdbcMapping) parameterType;
final Object parameterValue = enabledFilter.getParameter( parameterName ); final Object parameterValue = enabledFilter.getParameter( parameterName );
if ( parameterValue == null ) { if ( parameterValue == null ) {
throw new MappingException( String.format( "unknown parameter [%s] for filter [%s]", parameterName, filterName ) ); throw new MappingException( String.format( "unknown parameter [%s] for filter [%s]", parameterName, filterName ) );
} }
if ( parameterValue instanceof Iterable && !jdbcMapping.getJavaTypeDescriptor().isInstance( parameterValue ) ) {
final StringBuilder paramMarkers = new StringBuilder( "?" );
if ( parameterValue instanceof Iterable
&& !jdbcMapping.getJavaTypeDescriptor().isInstance( parameterValue ) ) {
final Iterator<?> iterator = ( (Iterable<?>) parameterValue ).iterator(); final Iterator<?> iterator = ( (Iterable<?>) parameterValue ).iterator();
if ( iterator.hasNext() ) { if ( iterator.hasNext() ) {
parameters.add( new FilterJdbcParameter( jdbcMapping, iterator.next() ) ); final Object value = iterator.next();
final FilterJdbcParameter jdbcParameter = new FilterJdbcParameter( jdbcMapping, value );
filterPredicate.applyParameter( jdbcParameter );
while ( iterator.hasNext() ) { while ( iterator.hasNext() ) {
sb.append( ",?" ); paramMarkers.append( ",?" );
parameters.add( new FilterJdbcParameter( jdbcMapping, iterator.next() ) ); filterPredicate.applyParameter( new FilterJdbcParameter( jdbcMapping, iterator.next() ) );
} }
} }
else { else {
// We need a dummy value if the list is empty // We need a dummy value if the list is empty
parameters.add( new FilterJdbcParameter( jdbcMapping, null ) ); filterPredicate.applyParameter( new FilterJdbcParameter( jdbcMapping, null ) );
} }
} }
else { else {
parameters.add( new FilterJdbcParameter( jdbcMapping, parameterValue ) ); filterPredicate.applyParameter( new FilterJdbcParameter( jdbcMapping, parameterValue ) );
}
final String marker = ":" + filterNames[ i ] + "." + parameterName;
condition = condition.replaceAll( marker, paramMarkers.toString() );
}
filterPredicate.applyFragment( condition );
} }
} }
sb.append( filterFragment, pos, filterFragment.length() );
return new FilterPredicate( sb.toString(), parameters ); if ( filterPredicate.isEmpty() ) {
return null;
}
return filterPredicate;
} }
} }

View File

@ -40,6 +40,8 @@ import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.NaturalIdMapping; import org.hibernate.metamodel.mapping.NaturalIdMapping;
import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.Restrictable;
import org.hibernate.metamodel.mapping.Restrictable.RestrictionPredicatePartType;
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping; import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
import org.hibernate.metamodel.mapping.internal.NonAggregatedIdentifierMappingImpl; import org.hibernate.metamodel.mapping.internal.NonAggregatedIdentifierMappingImpl;
import org.hibernate.metamodel.mapping.internal.SimpleForeignKeyDescriptor; import org.hibernate.metamodel.mapping.internal.SimpleForeignKeyDescriptor;
@ -363,12 +365,18 @@ public class LoaderSelectBuilder {
} }
private SelectStatement generateSelect() { private SelectStatement generateSelect() {
final Restrictable restrictable;
if ( loadable instanceof PluralAttributeMapping ) { if ( loadable instanceof PluralAttributeMapping ) {
final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) loadable; final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) loadable;
restrictable = (Restrictable) pluralAttributeMapping.getCollectionDescriptor();
if ( pluralAttributeMapping.getMappedType().getCollectionSemantics() instanceof BagSemantics ) { if ( pluralAttributeMapping.getMappedType().getCollectionSemantics() instanceof BagSemantics ) {
currentBagRole = pluralAttributeMapping.getNavigableRole().getNavigableName(); currentBagRole = pluralAttributeMapping.getNavigableRole().getNavigableName();
} }
} }
else {
restrictable = (Restrictable) loadable;
}
final NavigablePath rootNavigablePath = new NavigablePath( loadable.getRootPathName() ); final NavigablePath rootNavigablePath = new NavigablePath( loadable.getRootPathName() );
final QuerySpec rootQuerySpec = new QuerySpec( true ); final QuerySpec rootQuerySpec = new QuerySpec( true );
@ -393,6 +401,15 @@ public class LoaderSelectBuilder {
creationContext creationContext
); );
restrictable.applyRestrictions(
(predicate, partType, sourceType) -> rootQuerySpec.applyPredicate( predicate ),
rootTableGroup,
true,
loadQueryInfluencers.getEnabledFilters(),
Collections.emptySet(),
sqlAstCreationState.getFromClauseAccess()
);
rootQuerySpec.getFromClause().addRoot( rootTableGroup ); rootQuerySpec.getFromClause().addRoot( rootTableGroup );
sqlAstCreationState.getFromClauseAccess().registerTableGroup( rootNavigablePath, rootTableGroup ); sqlAstCreationState.getFromClauseAccess().registerTableGroup( rootNavigablePath, rootTableGroup );
registerPluralTableGroupParts( sqlAstCreationState.getFromClauseAccess(), rootTableGroup ); registerPluralTableGroupParts( sqlAstCreationState.getFromClauseAccess(), rootTableGroup );
@ -473,12 +490,8 @@ public class LoaderSelectBuilder {
if ( loadable instanceof PluralAttributeMapping ) { if ( loadable instanceof PluralAttributeMapping ) {
final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) loadable; final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) loadable;
applyFiltering( rootQuerySpec, rootTableGroup, pluralAttributeMapping, sqlAstCreationState.getFromClauseAccess() );
applyOrdering( rootTableGroup, pluralAttributeMapping ); applyOrdering( rootTableGroup, pluralAttributeMapping );
} }
else if ( loadable instanceof Joinable ) {
applyFiltering( rootQuerySpec, rootTableGroup, (Joinable) loadable, sqlAstCreationState.getFromClauseAccess() );
}
if ( orderByFragments != null ) { if ( orderByFragments != null ) {
orderByFragments.forEach( orderByFragments.forEach(
@ -588,7 +601,30 @@ public class LoaderSelectBuilder {
final CollectionPersister collectionPersister = pluralAttributeMapping.getCollectionDescriptor(); final CollectionPersister collectionPersister = pluralAttributeMapping.getCollectionDescriptor();
final Joinable joinable = collectionPersister.getCollectionType().getAssociatedJoinable( creationContext.getSessionFactory() ); final Joinable joinable = collectionPersister.getCollectionType().getAssociatedJoinable( creationContext.getSessionFactory() );
joinable.applyRestrictions( joinable.applyRestrictions(
querySpec, (predicate,partType,sourceType) -> {
if ( partType == RestrictionPredicatePartType.COLLECTION ) {
querySpec.applyPredicate( predicate );
}
else if ( partType == RestrictionPredicatePartType.MANY_TO_MANY ) {
final NavigablePath parentNavigablePath = tableGroup.getNavigablePath().getParent();
if ( parentNavigablePath == null ) {
querySpec.applyPredicate( predicate );
}
else {
final TableGroup parentTableGroup = fromClauseAccess.getTableGroup( parentNavigablePath );
TableGroupJoin pluralTableGroupJoin = null;
for ( TableGroupJoin nestedTableGroupJoin : parentTableGroup.getTableGroupJoins() ) {
if ( nestedTableGroupJoin.getNavigablePath() == tableGroup.getNavigablePath() ) {
pluralTableGroupJoin = nestedTableGroupJoin;
break;
}
}
assert pluralTableGroupJoin != null;
pluralTableGroupJoin.applyPredicate( predicate );
}
}
},
tableGroup, tableGroup,
true, true,
loadQueryInfluencers.getEnabledFilters(), loadQueryInfluencers.getEnabledFilters(),

View File

@ -14,9 +14,11 @@ import java.util.function.BiConsumer;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.hibernate.Filter;
import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.FilterAliasGenerator;
import org.hibernate.loader.ast.spi.Loadable; import org.hibernate.loader.ast.spi.Loadable;
import org.hibernate.loader.ast.spi.MultiNaturalIdLoader; import org.hibernate.loader.ast.spi.MultiNaturalIdLoader;
import org.hibernate.loader.ast.spi.NaturalIdLoader; import org.hibernate.loader.ast.spi.NaturalIdLoader;
@ -37,6 +39,7 @@ import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableReference; import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.ast.tree.from.TableReferenceJoin; import org.hibernate.sql.ast.tree.from.TableReferenceJoin;
import org.hibernate.sql.ast.tree.predicate.FilterPredicate;
import org.hibernate.sql.ast.tree.predicate.Predicate; import org.hibernate.sql.ast.tree.predicate.Predicate;
import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.DomainResultAssembler;
@ -493,4 +496,10 @@ public interface EntityMappingType extends ManagedMappingType, EntityValuedModel
default int getNumberOfFetchables() { default int getNumberOfFetchables() {
return getEntityPersister().getNumberOfFetchables(); return getEntityPersister().getNumberOfFetchables();
} }
FilterPredicate generateFilterPredicate(
TableGroup tableGroup,
boolean useQualifier,
Set<String> treatAsDeclarations,
Map<String, Filter> enabledFilters);
} }

View File

@ -0,0 +1,72 @@
/*
* 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.metamodel.mapping;
import java.util.Map;
import java.util.Set;
import org.hibernate.Filter;
import org.hibernate.persister.entity.Joinable;
import org.hibernate.sql.ast.spi.FromClauseAccess;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.predicate.Predicate;
import org.hibernate.sql.ast.tree.select.QuerySpec;
/**
* Things that can have {@link org.hibernate.annotations.Where}
* and {@link org.hibernate.annotations.Filter} applied to them -
* entities and collections
*/
public interface Restrictable {
/**
* Apply {@link org.hibernate.annotations.Filter} and
* {@link org.hibernate.annotations.Where} restrictions
*/
void applyRestrictions(
QuerySpec querySpec,
TableGroup tableGroup,
boolean useQualifier,
Map<String, Filter> enabledFilters,
Set<String> treatAsDeclarations,
FromClauseAccess fromClauseAccess);
/**
* Apply {@link org.hibernate.annotations.Filter} and
* {@link org.hibernate.annotations.Where} restrictions
*/
void applyRestrictions(
RestrictionPredicateConsumer predicateConsumer,
TableGroup tableGroup,
boolean useQualifier,
Map<String, Filter> enabledFilters,
Set<String> treatAsDeclarations,
FromClauseAccess fromClauseAccess);
enum RestrictionPredicatePartType {
ENTITY,
COLLECTION,
MANY_TO_MANY,
ONE_TO_MANY
}
enum RestrictionSourceType {
/**
* {@link org.hibernate.annotations.Where}
*/
WHERE,
/**
* {@link org.hibernate.annotations.Filter}
*/
FILTER
}
@FunctionalInterface
interface RestrictionPredicateConsumer {
void consume(Predicate predicate, Joinable.RestrictionPredicatePartType partType, Joinable.RestrictionSourceType sourceType);
}
}

View File

@ -17,6 +17,7 @@ import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.Consumer;
import org.hibernate.AssertionFailure; import org.hibernate.AssertionFailure;
import org.hibernate.FetchMode; import org.hibernate.FetchMode;
@ -119,7 +120,7 @@ import org.hibernate.sql.ast.tree.expression.AliasedExpression;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableGroupJoin; import org.hibernate.sql.ast.tree.from.TableGroupJoin;
import org.hibernate.sql.ast.tree.from.TableReference; import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.ast.tree.predicate.FilterPredicate; import org.hibernate.sql.ast.tree.predicate.Predicate;
import org.hibernate.sql.ast.tree.select.QuerySpec; import org.hibernate.sql.ast.tree.select.QuerySpec;
import org.hibernate.sql.ast.tree.select.SelectClause; import org.hibernate.sql.ast.tree.select.SelectClause;
import org.hibernate.sql.ast.tree.select.SelectStatement; import org.hibernate.sql.ast.tree.select.SelectStatement;
@ -134,7 +135,11 @@ import org.hibernate.type.Type;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import static org.hibernate.internal.FilterHelper.doCreateFilterPredicate; import static org.hibernate.metamodel.mapping.Restrictable.RestrictionPredicatePartType.COLLECTION;
import static org.hibernate.metamodel.mapping.Restrictable.RestrictionPredicatePartType.MANY_TO_MANY;
import static org.hibernate.metamodel.mapping.Restrictable.RestrictionPredicatePartType.ONE_TO_MANY;
import static org.hibernate.metamodel.mapping.Restrictable.RestrictionSourceType.FILTER;
import static org.hibernate.metamodel.mapping.Restrictable.RestrictionSourceType.WHERE;
/** /**
* Base implementation of the <tt>QueryableCollection</tt> interface. * Base implementation of the <tt>QueryableCollection</tt> interface.
@ -2036,47 +2041,71 @@ public abstract class AbstractCollectionPersister
applyOneToManyWhereRestriction( alias, tableGroup, querySpec, tableGroupJoin ); applyOneToManyWhereRestriction( alias, tableGroup, querySpec, tableGroupJoin );
} }
/**
* Apply both {@link org.hibernate.annotations.Filter} and
* {@link org.hibernate.annotations.Where} restrictions
*/
@Override
public void applyRestrictions(
RestrictionPredicateConsumer predicateConsumer,
TableGroup tableGroup,
boolean useQualifier,
Map<String, Filter> enabledFilters,
Set<String> treatAsDeclarations,
FromClauseAccess fromClauseAccess) {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// handle `@Filter`
applyFilterRestrictions( predicateConsumer, tableGroup, enabledFilters, fromClauseAccess );
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// handle `@Where`
TableReference tableReference;
if ( isManyToMany() ) {
tableReference = tableGroup.getPrimaryTableReference();
}
else if ( elementPersister instanceof Joinable ) {
tableReference = tableGroup.getTableReference( tableGroup.getNavigablePath(), ( (Joinable) elementPersister ).getTableName() );
}
else {
tableReference = tableGroup.getTableReference( tableGroup.getNavigablePath(), qualifiedTableName );
}
final String alias;
if ( tableReference == null ) {
alias = null;
}
else if ( useQualifier && tableReference.getIdentificationVariable() != null ) {
alias = tableReference.getIdentificationVariable();
}
else {
alias = tableReference.getTableExpression();
}
applyWhereRestriction( alias, (predicate) -> predicateConsumer.consume( predicate, COLLECTION, WHERE ) );
applyManyToManyWhereRestriction( tableGroup, (predicate) -> predicateConsumer.consume( predicate, MANY_TO_MANY, WHERE ) );
applyOneToManyWhereRestriction( alias, tableGroup, (predicate) -> predicateConsumer.consume( predicate, ONE_TO_MANY, WHERE ) );
}
protected void applyFilterRestrictions( protected void applyFilterRestrictions(
QuerySpec querySpec, QuerySpec querySpec,
TableGroup tableGroup, TableGroup tableGroup,
Map<String, Filter> enabledFilters, Map<String, Filter> enabledFilters,
TableGroupJoin pluralTableGroupJoin) { TableGroupJoin pluralTableGroupJoin) {
if ( filterHelper != null ) { if ( filterHelper != null ) {
final StringBuilder fragment = new StringBuilder(); filterHelper.applyFilters( querySpec, getFilterAliasGenerator( tableGroup ), enabledFilters );
filterHelper.render( fragment, getFilterAliasGenerator( tableGroup ), enabledFilters );
if ( fragment.length() > 1 ) {
final FilterPredicate filterPredicate = doCreateFilterPredicate( fragment.toString(), enabledFilters );
if ( pluralTableGroupJoin == null ) {
querySpec.applyPredicate( filterPredicate );
}
else {
pluralTableGroupJoin.applyPredicate( filterPredicate );
}
}
} }
if ( manyToManyFilterHelper != null ) { if ( manyToManyFilterHelper != null ) {
assert elementPersister instanceof Joinable; assert elementPersister instanceof Joinable;
assert isManyToMany(); assert isManyToMany();
final StringBuilder fragment = new StringBuilder(); manyToManyFilterHelper.applyFilters(
manyToManyFilterHelper.render( fragment, elementPersister.getFilterAliasGenerator( tableGroup ), enabledFilters ); getFilterAliasGenerator( tableGroup ),
if ( fragment.length() > 1 ) { enabledFilters,
final FilterPredicate filterPredicate = doCreateFilterPredicate( fragment.toString(), enabledFilters ); (predicate) -> {
if ( pluralTableGroupJoin == null ) { final NavigablePath parentNavigablePath = tableGroup.getNavigablePath().getParent();
querySpec.applyPredicate( filterPredicate ); if ( parentNavigablePath == null ) {
} querySpec.applyPredicate( predicate );
else {
pluralTableGroupJoin.applyPredicate( filterPredicate );
}
}
}
}
private static TableGroupJoin findTableGroupJoin(TableGroup tableGroup, FromClauseAccess fromClauseAccess) {
final NavigablePath parentNavigablePath;
if ( tableGroup == null || ( parentNavigablePath = tableGroup.getNavigablePath().getParent() ) == null ) {
return null;
} }
else { else {
final TableGroup parentTableGroup = fromClauseAccess.getTableGroup( parentNavigablePath ); final TableGroup parentTableGroup = fromClauseAccess.getTableGroup( parentNavigablePath );
@ -2088,6 +2117,37 @@ public abstract class AbstractCollectionPersister
} }
} }
assert pluralTableGroupJoin != null;
pluralTableGroupJoin.applyPredicate( predicate );
}
}
);
}
}
protected void applyFilterRestrictions(
RestrictionPredicateConsumer predicateConsumer,
TableGroup tableGroup,
Map<String, Filter> enabledFilters,
FromClauseAccess fromClauseAccess) {
if ( filterHelper != null ) {
filterHelper.applyFilters(
getFilterAliasGenerator( tableGroup ),
enabledFilters,
(filterPredicate) -> predicateConsumer.consume( filterPredicate, COLLECTION, FILTER )
);
}
if ( manyToManyFilterHelper != null ) {
assert elementPersister instanceof Joinable;
assert isManyToMany();
final TableReference tableReference = tableGroup.resolveTableReference( ( (Joinable) elementPersister ).getTableName() );
manyToManyFilterHelper.applyFilters(
getFilterAliasGenerator( tableReference.getIdentificationVariable() ),
enabledFilters,
(filterPredicate) -> predicateConsumer.consume( filterPredicate, MANY_TO_MANY, FILTER )
);
assert pluralTableGroupJoin != null; assert pluralTableGroupJoin != null;
return pluralTableGroupJoin; return pluralTableGroupJoin;
} }
@ -2097,16 +2157,14 @@ public abstract class AbstractCollectionPersister
String alias, String alias,
QuerySpec querySpec, QuerySpec querySpec,
TableGroupJoin pluralTableGroupJoin) { TableGroupJoin pluralTableGroupJoin) {
applyWhereRestriction( alias, querySpec::applyPredicate );
}
protected void applyWhereRestriction(String alias, Consumer<Predicate> predicateConsumer) {
if ( sqlWhereString != null ) { if ( sqlWhereString != null ) {
final String whereCondition = getSQLWhereString( alias ); final String whereCondition = getSQLWhereString( alias );
assert whereCondition != null; assert whereCondition != null;
final WhereFilterPredicate filterPredicate = new WhereFilterPredicate( whereCondition ); predicateConsumer.accept( new WhereFilterPredicate( whereCondition ) );
if ( pluralTableGroupJoin == null ) {
querySpec.applyPredicate( filterPredicate );
}
else {
pluralTableGroupJoin.applyPredicate( filterPredicate );
}
} }
} }
@ -2114,6 +2172,10 @@ public abstract class AbstractCollectionPersister
TableGroup tableGroup, TableGroup tableGroup,
QuerySpec querySpec, QuerySpec querySpec,
TableGroupJoin pluralTableGroupJoin) { TableGroupJoin pluralTableGroupJoin) {
applyManyToManyWhereRestriction( tableGroup, querySpec::applyPredicate );
}
public void applyManyToManyWhereRestriction(TableGroup tableGroup, Consumer<Predicate> predicateConsumer) {
if ( manyToManyWhereString == null ) { if ( manyToManyWhereString == null ) {
return; return;
} }
@ -2121,13 +2183,7 @@ public abstract class AbstractCollectionPersister
final TableReference tableReference = tableGroup.resolveTableReference( ( (Joinable) elementPersister ).getTableName() ); final TableReference tableReference = tableGroup.resolveTableReference( ( (Joinable) elementPersister ).getTableName() );
final String condition = StringHelper.replace( manyToManyWhereTemplate, Template.TEMPLATE, tableReference.getIdentificationVariable() ); final String condition = StringHelper.replace( manyToManyWhereTemplate, Template.TEMPLATE, tableReference.getIdentificationVariable() );
assert StringHelper.isNotEmpty( condition ); assert StringHelper.isNotEmpty( condition );
final WhereFilterPredicate filterPredicate = new WhereFilterPredicate( condition ); predicateConsumer.accept( new WhereFilterPredicate( condition ) );
if ( pluralTableGroupJoin == null ) {
querySpec.applyPredicate( filterPredicate );
}
else {
pluralTableGroupJoin.applyPredicate( filterPredicate );
}
} }
private void applyOneToManyWhereRestriction( private void applyOneToManyWhereRestriction(
@ -2135,6 +2191,10 @@ public abstract class AbstractCollectionPersister
TableGroup tableGroup, TableGroup tableGroup,
QuerySpec querySpec, QuerySpec querySpec,
TableGroupJoin pluralTableGroupJoin) { TableGroupJoin pluralTableGroupJoin) {
applyOneToManyWhereRestriction( alias, tableGroup, querySpec::applyPredicate );
}
private void applyOneToManyWhereRestriction(String alias, TableGroup tableGroup, Consumer<Predicate> predicateConsumer) {
if ( ! isOneToMany() ) { if ( ! isOneToMany() ) {
return; return;
} }
@ -2145,13 +2205,7 @@ public abstract class AbstractCollectionPersister
final String associationWhereCondition = ( (Joinable) getElementPersister() ).oneToManyFilterFragment( alias, null ); final String associationWhereCondition = ( (Joinable) getElementPersister() ).oneToManyFilterFragment( alias, null );
if ( StringHelper.isNotEmpty( associationWhereCondition ) ) { if ( StringHelper.isNotEmpty( associationWhereCondition ) ) {
final WhereFilterPredicate filterPredicate = new WhereFilterPredicate( associationWhereCondition ); predicateConsumer.accept( new WhereFilterPredicate( associationWhereCondition ) );
if ( pluralTableGroupJoin == null ) {
querySpec.applyPredicate( filterPredicate );
}
else {
pluralTableGroupJoin.applyPredicate( filterPredicate );
}
} }
} }

View File

@ -268,8 +268,6 @@ import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.java.MutabilityPlan; import org.hibernate.type.descriptor.java.MutabilityPlan;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
import static org.hibernate.internal.FilterHelper.doCreateFilterPredicate;
/** /**
* Basic functionality for persisting an entity via JDBC * Basic functionality for persisting an entity via JDBC
* through either generated or custom SQL * through either generated or custom SQL
@ -1052,7 +1050,12 @@ public abstract class AbstractEntityPersister
propertyDefinedOnSubclass = ArrayHelper.toBooleanArray( definedBySubclass ); propertyDefinedOnSubclass = ArrayHelper.toBooleanArray( definedBySubclass );
// Handle any filters applied to the class level // Handle any filters applied to the class level
if ( CollectionHelper.isEmpty( bootDescriptor.getFilters() ) ) {
filterHelper = null;
}
else {
filterHelper = new FilterHelper( bootDescriptor.getFilters(), factory ); filterHelper = new FilterHelper( bootDescriptor.getFilters(), factory );
}
// Check if we can use Reference Cached entities in 2lc // Check if we can use Reference Cached entities in 2lc
// todo : should really validate that the cache access type is read-only // todo : should really validate that the cache access type is read-only
@ -1337,7 +1340,7 @@ public abstract class AbstractEntityPersister
creationContext creationContext
); );
return new StandardTableGroup( final StandardTableGroup tableGroup = new StandardTableGroup(
canUseInnerJoins, canUseInnerJoins,
navigablePath, navigablePath,
this, this,
@ -1346,10 +1349,10 @@ public abstract class AbstractEntityPersister
true, true,
sqlAliasBase, sqlAliasBase,
(tableExpression) -> ArrayHelper.contains( getSubclassTableNames(), tableExpression ), (tableExpression) -> ArrayHelper.contains( getSubclassTableNames(), tableExpression ),
(tableExpression, tableGroup) -> { (tableExpression, tg) -> {
final String[] subclassTableNames = getSubclassTableNames(); final String[] subclassTableNames = getSubclassTableNames();
for ( int i = 0; i < subclassTableNames.length; i++ ) { for ( int i = 0; i < subclassTableNames.length; i++ ) {
if ( tableExpression.equals( subclassTableNames[i] ) ) { if ( tableExpression.equals( subclassTableNames[ i ] ) ) {
final boolean isNullableTable = isNullableSubclassTable( i ); final boolean isNullableTable = isNullableSubclassTable( i );
final TableReference joinedTableReference = new TableReference( final TableReference joinedTableReference = new TableReference(
tableExpression, tableExpression,
@ -1380,6 +1383,8 @@ public abstract class AbstractEntityPersister
}, },
getFactory() getFactory()
); );
return tableGroup;
} }
@Override @Override
@ -3992,6 +3997,10 @@ public abstract class AbstractEntityPersister
@Override @Override
public String filterFragment(String alias, Map<String, Filter> enabledFilters, Set<String> treatAsDeclarations) { public String filterFragment(String alias, Map<String, Filter> enabledFilters, Set<String> treatAsDeclarations) {
if ( filterHelper == null ) {
return "";
}
final StringBuilder sessionFilterFragment = new StringBuilder(); final StringBuilder sessionFilterFragment = new StringBuilder();
filterHelper.render( sessionFilterFragment, alias == null ? null : getFilterAliasGenerator( alias ), enabledFilters ); filterHelper.render( sessionFilterFragment, alias == null ? null : getFilterAliasGenerator( alias ), enabledFilters );
final String filterFragment = filterFragment( alias, treatAsDeclarations ); final String filterFragment = filterFragment( alias, treatAsDeclarations );
@ -4007,6 +4016,10 @@ public abstract class AbstractEntityPersister
Map<String, Filter> enabledFilters, Map<String, Filter> enabledFilters,
Set<String> treatAsDeclarations, Set<String> treatAsDeclarations,
boolean useIdentificationVariable) { boolean useIdentificationVariable) {
if ( filterHelper == null ) {
return null;
}
final String alias; final String alias;
if ( tableGroup == null ) { if ( tableGroup == null ) {
alias = null; alias = null;
@ -4017,6 +4030,7 @@ public abstract class AbstractEntityPersister
else { else {
alias = tableGroup.getPrimaryTableReference().getTableExpression(); alias = tableGroup.getPrimaryTableReference().getTableExpression();
} }
final StringBuilder sessionFilterFragment = new StringBuilder(); final StringBuilder sessionFilterFragment = new StringBuilder();
filterHelper.render( sessionFilterFragment, !useIdentificationVariable || tableGroup == null ? null : getFilterAliasGenerator( tableGroup ), enabledFilters ); filterHelper.render( sessionFilterFragment, !useIdentificationVariable || tableGroup == null ? null : getFilterAliasGenerator( tableGroup ), enabledFilters );
final String filterFragment = filterFragment( alias, treatAsDeclarations ); final String filterFragment = filterFragment( alias, treatAsDeclarations );
@ -4030,6 +4044,42 @@ public abstract class AbstractEntityPersister
return alias; return alias;
} }
@Override
public void applyRestrictions(
RestrictionPredicateConsumer predicateConsumer,
TableGroup tableGroup,
boolean useQualifier,
Map<String, Filter> enabledFilters,
Set<String> treatAsDeclarations,
FromClauseAccess fromClauseAccess) {
// handle `@Filter`
final FilterAliasGenerator aliasGenerator = useQualifier && tableGroup != null
? getFilterAliasGenerator( tableGroup )
: null;
applyFilterRestrictions(
enabledFilters,
aliasGenerator,
(predicate) -> predicateConsumer.consume( predicate, RestrictionPredicatePartType.ENTITY, RestrictionSourceType.FILTER )
);
// handle `@Where`
final String alias;
if ( tableGroup == null ) {
alias = null;
}
else if ( useQualifier && tableGroup.getPrimaryTableReference().getIdentificationVariable() != null ) {
alias = tableGroup.getPrimaryTableReference().getIdentificationVariable();
}
else {
alias = tableGroup.getPrimaryTableReference().getTableExpression();
}
applyWhereRestriction(
generateWhereConditionAlias( alias ),
treatAsDeclarations,
(predicate) -> predicateConsumer.consume( predicate, RestrictionPredicatePartType.ENTITY, RestrictionSourceType.WHERE )
);
}
/** /**
* Apply both {@link org.hibernate.annotations.Filter} and * Apply both {@link org.hibernate.annotations.Filter} and
* {@link org.hibernate.annotations.Where} restrictions * {@link org.hibernate.annotations.Where} restrictions
@ -4048,7 +4098,7 @@ public abstract class AbstractEntityPersister
final FilterAliasGenerator aliasGenerator = useQualifier && tableGroup != null final FilterAliasGenerator aliasGenerator = useQualifier && tableGroup != null
? getFilterAliasGenerator( tableGroup ) ? getFilterAliasGenerator( tableGroup )
: null; : null;
applyFilterRestrictions( querySpec, tableGroup, enabledFilters, aliasGenerator, tableGroupJoin ); applyFilterRestrictions( querySpec, enabledFilters, aliasGenerator, tableGroupJoin );
// handle `@Where` // handle `@Where`
final String alias; final String alias;
@ -4064,22 +4114,31 @@ public abstract class AbstractEntityPersister
applyWhereRestriction( generateWhereConditionAlias( alias ), treatAsDeclarations, querySpec, tableGroupJoin ); applyWhereRestriction( generateWhereConditionAlias( alias ), treatAsDeclarations, querySpec, tableGroupJoin );
} }
@Override
public FilterPredicate generateFilterPredicate(TableGroup tableGroup, boolean useQualifier, Set<String> treatAsDeclarations, Map<String, Filter> enabledFilters) {
if ( filterHelper == null ) {
return null;
}
final FilterAliasGenerator aliasGenerator = useQualifier && tableGroup != null
? getFilterAliasGenerator( tableGroup )
: null;
return filterHelper.generateFilterPredicate( aliasGenerator, enabledFilters );
}
protected void applyFilterRestrictions( protected void applyFilterRestrictions(
QuerySpec querySpec, QuerySpec querySpec,
TableGroup tableGroup,
Map<String, Filter> enabledFilters, Map<String, Filter> enabledFilters,
FilterAliasGenerator aliasGenerator, FilterAliasGenerator aliasGenerator) {
TableGroupJoin tableGroupJoin) { if ( filterHelper != null ) {
final StringBuilder fragment = new StringBuilder(); filterHelper.applyFilters( querySpec, aliasGenerator, enabledFilters );
filterHelper.render( fragment, aliasGenerator, enabledFilters );
if ( fragment.length() > 1 ) {
final FilterPredicate filterPredicate = doCreateFilterPredicate( fragment.toString(), enabledFilters );
if ( tableGroupJoin == null ) {
querySpec.applyPredicate( filterPredicate );
} }
else {
tableGroupJoin.applyPredicate( filterPredicate );
} }
protected void applyFilterRestrictions(
Map<String, Filter> enabledFilters, FilterAliasGenerator aliasGenerator, Consumer<Predicate> predicateConsumer) {
if ( filterHelper != null ) {
filterHelper.applyFilters( aliasGenerator, enabledFilters, (Consumer) predicateConsumer );
} }
} }
@ -4116,6 +4175,13 @@ public abstract class AbstractEntityPersister
} }
} }
protected void applyWhereRestriction(String alias, Set<String> treatAsDeclarations, Consumer<Predicate> predicateConsumer) {
if ( hasWhere() ) {
final String whereCondition = getSQLWhereString( alias );
predicateConsumer.accept( new WhereFilterPredicate( whereCondition ) );
}
}
public String generateFilterConditionAlias(String rootAlias) { public String generateFilterConditionAlias(String rootAlias) {
return rootAlias; return rootAlias;
} }
@ -4398,7 +4464,7 @@ public abstract class AbstractEntityPersister
@Override @Override
public boolean isAffectedByEnabledFilters(LoadQueryInfluencers loadQueryInfluencers) { public boolean isAffectedByEnabledFilters(LoadQueryInfluencers loadQueryInfluencers) {
if ( loadQueryInfluencers.hasEnabledFilters() ) { if ( loadQueryInfluencers.hasEnabledFilters() && filterHelper != null ) {
if ( filterHelper.isAffectedBy( loadQueryInfluencers.getEnabledFilters() ) ) { if ( filterHelper.isAffectedBy( loadQueryInfluencers.getEnabledFilters() ) ) {
return true; return true;
} }

View File

@ -5,15 +5,15 @@
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.persister.entity; package org.hibernate.persister.entity;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.hibernate.Filter; import org.hibernate.Filter;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.sql.ast.spi.FromClauseAccess; import org.hibernate.metamodel.mapping.Restrictable;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.select.QuerySpec;
/** /**
* Anything that can be loaded by outer join - namely * Anything that can be loaded by outer join - namely
@ -21,7 +21,7 @@ import org.hibernate.sql.ast.tree.select.QuerySpec;
* *
* @author Gavin King * @author Gavin King
*/ */
public interface Joinable { public interface Joinable extends Restrictable {
//should this interface extend PropertyMapping? //should this interface extend PropertyMapping?
/** /**
@ -38,18 +38,6 @@ public interface Joinable {
*/ */
public String[] getKeyColumnNames(); public String[] getKeyColumnNames();
/**
* Apply {@link org.hibernate.annotations.Filter} and
* {@link org.hibernate.annotations.Where} restrictions
*/
void applyRestrictions(
QuerySpec querySpec,
TableGroup tableGroup,
boolean useQualifier,
Map<String, Filter> enabledFilters,
Set<String> treatAsDeclarations,
FromClauseAccess fromClauseAccess);
/** /**
* Get the where clause filter, given a query alias and considering enabled session filters * Get the where clause filter, given a query alias and considering enabled session filters
*/ */

View File

@ -116,15 +116,13 @@ public class MatchingIdSelectionHelper {
); );
sqmConverter.getProcessingStateStack().pop(); sqmConverter.getProcessingStateStack().pop();
final FilterPredicate filterPredicate = FilterHelper.createFilterPredicate( final FilterPredicate filterPredicate = targetEntityDescriptor.getEntityPersister().generateFilterPredicate(
executionContext.getSession().getLoadQueryInfluencers(), mutatingTableGroup,
(Joinable) targetEntityDescriptor.getEntityPersister(), true,
mutatingTableGroup Collections.emptySet(),
executionContext.getSession().getLoadQueryInfluencers().getEnabledFilters()
); );
if ( filterPredicate != null ) { idSelectionQuery.applyPredicate( SqlAstTreeHelper.combinePredicates( restriction, filterPredicate ) );
restriction = SqlAstTreeHelper.combinePredicates( restriction, filterPredicate );
}
idSelectionQuery.applyPredicate( restriction );
return new SelectStatement( idSelectionQuery, domainResults ); return new SelectStatement( idSelectionQuery, domainResults );
} }

View File

@ -156,10 +156,11 @@ public class RestrictedDeleteExecutionDelegate implements TableBasedDeleteHandle
} }
); );
final FilterPredicate filterPredicate = FilterHelper.createFilterPredicate( final FilterPredicate filterPredicate = entityDescriptor.generateFilterPredicate(
executionContext.getSession().getLoadQueryInfluencers(), deletingTableGroup,
(Joinable) entityDescriptor, true,
deletingTableGroup Collections.emptySet(),
executionContext.getSession().getLoadQueryInfluencers().getEnabledFilters()
); );
if ( filterPredicate != null ) { if ( filterPredicate != null ) {
needsIdTableWrapper.setValue( true ); needsIdTableWrapper.setValue( true );

View File

@ -186,10 +186,11 @@ public class TableBasedUpdateHandler
assert predicate != null; assert predicate != null;
} }
final FilterPredicate filterPredicate = FilterHelper.createFilterPredicate( final FilterPredicate filterPredicate = entityDescriptor.generateFilterPredicate(
executionContext.getSession().getLoadQueryInfluencers(), updatingTableGroup,
(Joinable) rootEntityDescriptor, true,
updatingTableGroup Collections.emptySet(),
executionContext.getSession().getLoadQueryInfluencers().getEnabledFilters()
); );
if ( filterPredicate != null ) { if ( filterPredicate != null ) {
predicate = SqlAstTreeHelper.combinePredicates( predicate, filterPredicate ); predicate = SqlAstTreeHelper.combinePredicates( predicate, filterPredicate );

View File

@ -26,7 +26,6 @@ import java.util.function.BiConsumer;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
import jakarta.persistence.TemporalType;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.Internal; import org.hibernate.Internal;
@ -47,7 +46,6 @@ import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.OptimizableGenerator; import org.hibernate.id.OptimizableGenerator;
import org.hibernate.id.PostInsertIdentifierGenerator; import org.hibernate.id.PostInsertIdentifierGenerator;
import org.hibernate.id.enhanced.Optimizer; import org.hibernate.id.enhanced.Optimizer;
import org.hibernate.internal.FilterHelper;
import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.internal.util.collections.Stack; import org.hibernate.internal.util.collections.Stack;
import org.hibernate.internal.util.collections.StandardStack; import org.hibernate.internal.util.collections.StandardStack;
@ -62,6 +60,7 @@ import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.metamodel.mapping.Bindable; import org.hibernate.metamodel.mapping.Bindable;
import org.hibernate.metamodel.mapping.CollectionPart; import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.ConvertibleModelPart; import org.hibernate.metamodel.mapping.ConvertibleModelPart;
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
import org.hibernate.metamodel.mapping.EntityAssociationMapping; import org.hibernate.metamodel.mapping.EntityAssociationMapping;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping; import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
@ -70,18 +69,18 @@ import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.EntityValuedModelPart; import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.metamodel.mapping.EntityVersionMapping; import org.hibernate.metamodel.mapping.EntityVersionMapping;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.JdbcMappingContainer; import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.metamodel.mapping.MappingModelExpressable; import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.ModelPartContainer; import org.hibernate.metamodel.mapping.ModelPartContainer;
import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.Restrictable;
import org.hibernate.metamodel.mapping.Restrictable.RestrictionPredicatePartType;
import org.hibernate.metamodel.mapping.SqlExpressable; import org.hibernate.metamodel.mapping.SqlExpressable;
import org.hibernate.metamodel.mapping.ValueMapping; import org.hibernate.metamodel.mapping.ValueMapping;
import org.hibernate.metamodel.mapping.internal.EmbeddedCollectionPart; import org.hibernate.metamodel.mapping.internal.EmbeddedCollectionPart;
import org.hibernate.metamodel.mapping.internal.EntityCollectionPart; import org.hibernate.metamodel.mapping.internal.EntityCollectionPart;
import org.hibernate.metamodel.mapping.internal.ExplicitColumnDiscriminatorMappingImpl;
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
import org.hibernate.metamodel.mapping.ordering.OrderByFragment; import org.hibernate.metamodel.mapping.ordering.OrderByFragment;
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter; import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
@ -121,6 +120,8 @@ import org.hibernate.query.QueryLogging;
import org.hibernate.query.SemanticException; import org.hibernate.query.SemanticException;
import org.hibernate.query.TemporalUnit; import org.hibernate.query.TemporalUnit;
import org.hibernate.query.UnaryArithmeticOperator; import org.hibernate.query.UnaryArithmeticOperator;
import org.hibernate.query.criteria.JpaPath;
import org.hibernate.query.internal.QueryHelper;
import org.hibernate.query.spi.QueryOptions; import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.QueryParameterBinding; import org.hibernate.query.spi.QueryParameterBinding;
import org.hibernate.query.spi.QueryParameterBindings; import org.hibernate.query.spi.QueryParameterBindings;
@ -131,8 +132,10 @@ import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.SqmQuerySource; import org.hibernate.query.sqm.SqmQuerySource;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.function.SelfRenderingAggregateFunctionSqlAstExpression; import org.hibernate.query.sqm.function.SelfRenderingAggregateFunctionSqlAstExpression;
import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
import org.hibernate.query.sqm.internal.DomainParameterXref; import org.hibernate.query.sqm.internal.DomainParameterXref;
import org.hibernate.query.sqm.internal.SqmMappingModelHelper; import org.hibernate.query.sqm.internal.SqmMappingModelHelper;
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
import org.hibernate.query.sqm.spi.BaseSemanticQueryWalker; import org.hibernate.query.sqm.spi.BaseSemanticQueryWalker;
import org.hibernate.query.sqm.sql.internal.BasicValuedPathInterpretation; import org.hibernate.query.sqm.sql.internal.BasicValuedPathInterpretation;
import org.hibernate.query.sqm.sql.internal.DiscriminatedAssociationPathInterpretation; import org.hibernate.query.sqm.sql.internal.DiscriminatedAssociationPathInterpretation;
@ -148,6 +151,7 @@ import org.hibernate.query.sqm.sql.internal.SqmMapEntryResult;
import org.hibernate.query.sqm.sql.internal.SqmParameterInterpretation; import org.hibernate.query.sqm.sql.internal.SqmParameterInterpretation;
import org.hibernate.query.sqm.sql.internal.SqmPathInterpretation; import org.hibernate.query.sqm.sql.internal.SqmPathInterpretation;
import org.hibernate.query.sqm.sql.internal.TypeHelper; import org.hibernate.query.sqm.sql.internal.TypeHelper;
import org.hibernate.query.sqm.tree.SqmJoinType;
import org.hibernate.query.sqm.tree.SqmStatement; import org.hibernate.query.sqm.tree.SqmStatement;
import org.hibernate.query.sqm.tree.SqmTypedNode; import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.query.sqm.tree.cte.SqmCteContainer; import org.hibernate.query.sqm.tree.cte.SqmCteContainer;
@ -160,6 +164,8 @@ import org.hibernate.query.sqm.tree.domain.AbstractSqmSpecificPluralPartPath;
import org.hibernate.query.sqm.tree.domain.NonAggregatedCompositeSimplePath; import org.hibernate.query.sqm.tree.domain.NonAggregatedCompositeSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmAnyValuedSimplePath; import org.hibernate.query.sqm.tree.domain.SqmAnyValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath; import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmCorrelatedRootJoin;
import org.hibernate.query.sqm.tree.domain.SqmCorrelation;
import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath; import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath; import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmIndexedCollectionAccessPath; import org.hibernate.query.sqm.tree.domain.SqmIndexedCollectionAccessPath;
@ -171,6 +177,7 @@ import org.hibernate.query.sqm.tree.domain.SqmMinIndexPath;
import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.domain.SqmPluralValuedSimplePath; import org.hibernate.query.sqm.tree.domain.SqmPluralValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath; import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
import org.hibernate.query.sqm.tree.domain.SqmTreatedRoot;
import org.hibernate.query.sqm.tree.expression.Conversion; import org.hibernate.query.sqm.tree.expression.Conversion;
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter; import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
import org.hibernate.query.sqm.tree.expression.SqmAliasedNodeRef; import org.hibernate.query.sqm.tree.expression.SqmAliasedNodeRef;
@ -195,6 +202,7 @@ import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
import org.hibernate.query.sqm.tree.expression.SqmLiteral; import org.hibernate.query.sqm.tree.expression.SqmLiteral;
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType; import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
import org.hibernate.query.sqm.tree.expression.SqmLiteralNull; import org.hibernate.query.sqm.tree.expression.SqmLiteralNull;
import org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression;
import org.hibernate.query.sqm.tree.expression.SqmNamedParameter; import org.hibernate.query.sqm.tree.expression.SqmNamedParameter;
import org.hibernate.query.sqm.tree.expression.SqmParameter; import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.query.sqm.tree.expression.SqmParameterizedEntityType; import org.hibernate.query.sqm.tree.expression.SqmParameterizedEntityType;
@ -213,6 +221,7 @@ import org.hibernate.query.sqm.tree.from.SqmFromClause;
import org.hibernate.query.sqm.tree.from.SqmJoin; import org.hibernate.query.sqm.tree.from.SqmJoin;
import org.hibernate.query.sqm.tree.from.SqmRoot; import org.hibernate.query.sqm.tree.from.SqmRoot;
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement; import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
import org.hibernate.query.sqm.tree.insert.SqmInsertStatement;
import org.hibernate.query.sqm.tree.insert.SqmInsertValuesStatement; import org.hibernate.query.sqm.tree.insert.SqmInsertValuesStatement;
import org.hibernate.query.sqm.tree.insert.SqmValues; import org.hibernate.query.sqm.tree.insert.SqmValues;
import org.hibernate.query.sqm.tree.predicate.SqmAndPredicate; import org.hibernate.query.sqm.tree.predicate.SqmAndPredicate;
@ -289,16 +298,21 @@ import org.hibernate.sql.ast.tree.expression.ExtractUnit;
import org.hibernate.sql.ast.tree.expression.Format; import org.hibernate.sql.ast.tree.expression.Format;
import org.hibernate.sql.ast.tree.expression.JdbcLiteral; import org.hibernate.sql.ast.tree.expression.JdbcLiteral;
import org.hibernate.sql.ast.tree.expression.JdbcParameter; import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.expression.ModifiedSubQueryExpression;
import org.hibernate.sql.ast.tree.expression.Over;
import org.hibernate.sql.ast.tree.expression.QueryLiteral; import org.hibernate.sql.ast.tree.expression.QueryLiteral;
import org.hibernate.sql.ast.tree.expression.SelfRenderingExpression; import org.hibernate.sql.ast.tree.expression.SelfRenderingExpression;
import org.hibernate.sql.ast.tree.expression.SelfRenderingSqlFragmentExpression;
import org.hibernate.sql.ast.tree.expression.SqlSelectionExpression; import org.hibernate.sql.ast.tree.expression.SqlSelectionExpression;
import org.hibernate.sql.ast.tree.expression.SqlTuple; import org.hibernate.sql.ast.tree.expression.SqlTuple;
import org.hibernate.sql.ast.tree.expression.Star; import org.hibernate.sql.ast.tree.expression.Star;
import org.hibernate.sql.ast.tree.expression.Summarization; import org.hibernate.sql.ast.tree.expression.Summarization;
import org.hibernate.sql.ast.tree.expression.TrimSpecification; import org.hibernate.sql.ast.tree.expression.TrimSpecification;
import org.hibernate.sql.ast.tree.expression.UnaryOperation; import org.hibernate.sql.ast.tree.expression.UnaryOperation;
import org.hibernate.sql.ast.tree.from.CorrelatedPluralTableGroup;
import org.hibernate.sql.ast.tree.from.CorrelatedTableGroup; import org.hibernate.sql.ast.tree.from.CorrelatedTableGroup;
import org.hibernate.sql.ast.tree.from.LazyTableGroup; import org.hibernate.sql.ast.tree.from.LazyTableGroup;
import org.hibernate.sql.ast.tree.from.PluralTableGroup;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableGroupJoin; import org.hibernate.sql.ast.tree.from.TableGroupJoin;
import org.hibernate.sql.ast.tree.from.TableGroupJoinProducer; import org.hibernate.sql.ast.tree.from.TableGroupJoinProducer;
@ -331,6 +345,7 @@ import org.hibernate.sql.ast.tree.update.Assignment;
import org.hibernate.sql.ast.tree.update.UpdateStatement; import org.hibernate.sql.ast.tree.update.UpdateStatement;
import org.hibernate.sql.exec.internal.JdbcParameterImpl; import org.hibernate.sql.exec.internal.JdbcParameterImpl;
import org.hibernate.sql.exec.internal.JdbcParametersImpl; import org.hibernate.sql.exec.internal.JdbcParametersImpl;
import org.hibernate.sql.exec.internal.VersionTypeSeedParameterSpecification;
import org.hibernate.sql.exec.spi.ExecutionContext; import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.exec.spi.JdbcParameterBindings; import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.sql.exec.spi.JdbcParameters; import org.hibernate.sql.exec.spi.JdbcParameters;
@ -352,6 +367,8 @@ import org.hibernate.usertype.UserVersionType;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import jakarta.persistence.TemporalType;
import static org.hibernate.internal.util.NullnessHelper.coalesceSuppliedValues; import static org.hibernate.internal.util.NullnessHelper.coalesceSuppliedValues;
import static org.hibernate.query.BinaryArithmeticOperator.ADD; import static org.hibernate.query.BinaryArithmeticOperator.ADD;
import static org.hibernate.query.BinaryArithmeticOperator.MULTIPLY; import static org.hibernate.query.BinaryArithmeticOperator.MULTIPLY;
@ -391,7 +408,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
private ForeignKeyDescriptor.Nature currentlyResolvingForeignKeySide; private ForeignKeyDescriptor.Nature currentlyResolvingForeignKeySide;
private SqmQueryPart<?> currentSqmQueryPart; private SqmQueryPart<?> currentSqmQueryPart;
private Map<String, FilterPredicate> collectionFilterPredicates; private final Map<String, List<Predicate>> collectionFilterPredicates = new HashMap<>();
private List<Map.Entry<OrderByFragment, TableGroup>> orderByFragments; private List<Map.Entry<OrderByFragment, TableGroup>> orderByFragments;
private final SqlAliasBaseManager sqlAliasBaseManager = new SqlAliasBaseManager(); private final SqlAliasBaseManager sqlAliasBaseManager = new SqlAliasBaseManager();
@ -670,12 +687,11 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
final List<Assignment> assignments = visitSetClause( sqmStatement.getSetClause() ); final List<Assignment> assignments = visitSetClause( sqmStatement.getSetClause() );
addVersionedAssignment( assignments::add, sqmStatement ); addVersionedAssignment( assignments::add, sqmStatement );
final FilterPredicate filterPredicate = FilterHelper.createFilterPredicate( final FilterPredicate filterPredicate = entityDescriptor.generateFilterPredicate(
getLoadQueryInfluencers(),
(Joinable) entityDescriptor,
rootTableGroup, rootTableGroup,
// todo (6.0): this is temporary until we implement proper alias support AbstractSqlAstTranslator.rendersTableReferenceAlias( Clause.UPDATE ),
AbstractSqlAstTranslator.rendersTableReferenceAlias( Clause.UPDATE ) Collections.emptySet(),
loadQueryInfluencers.getEnabledFilters()
); );
if ( filterPredicate != null ) { if ( filterPredicate != null ) {
additionalRestrictions = SqlAstTreeHelper.combinePredicates( additionalRestrictions, filterPredicate ); additionalRestrictions = SqlAstTreeHelper.combinePredicates( additionalRestrictions, filterPredicate );
@ -900,12 +916,11 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
throw new HibernateException( "Not expecting multiple table references for an SQM DELETE" ); throw new HibernateException( "Not expecting multiple table references for an SQM DELETE" );
} }
final FilterPredicate filterPredicate = FilterHelper.createFilterPredicate( final FilterPredicate filterPredicate = entityDescriptor.generateFilterPredicate(
getLoadQueryInfluencers(),
(Joinable) entityDescriptor,
rootTableGroup, rootTableGroup,
// todo (6.0): this is temporary until we implement proper alias support AbstractSqlAstTranslator.rendersTableReferenceAlias( Clause.DELETE ),
AbstractSqlAstTranslator.rendersTableReferenceAlias( Clause.DELETE ) Collections.emptySet(),
loadQueryInfluencers.getEnabledFilters()
); );
if ( filterPredicate != null ) { if ( filterPredicate != null ) {
additionalRestrictions = SqlAstTreeHelper.combinePredicates( additionalRestrictions, filterPredicate ); additionalRestrictions = SqlAstTreeHelper.combinePredicates( additionalRestrictions, filterPredicate );
@ -1747,22 +1762,17 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
final ModelPartContainer modelPartContainer = root.getModelPart(); final ModelPartContainer modelPartContainer = root.getModelPart();
final EntityPersister entityPersister = modelPartContainer.findContainingEntityMapping().getEntityPersister(); final EntityPersister entityPersister = modelPartContainer.findContainingEntityMapping().getEntityPersister();
assert entityPersister instanceof Joinable; assert entityPersister instanceof Joinable;
final FilterPredicate filterPredicate = FilterHelper.createFilterPredicate(
getLoadQueryInfluencers(), (Joinable) entityPersister, root
);
if ( filterPredicate != null ) {
sqlQuerySpec.applyPredicate( filterPredicate );
}
if ( CollectionHelper.isNotEmpty( collectionFilterPredicates ) ) { if ( CollectionHelper.isNotEmpty( collectionFilterPredicates ) ) {
root.getTableGroupJoins().forEach( root.getTableGroupJoins().forEach( (tableGroupJoin) -> {
tableGroupJoin -> { collectionFilterPredicates.forEach( (alias, predicates) -> {
collectionFilterPredicates.forEach( (alias, predicate) -> {
if ( tableGroupJoin.getJoinedGroup().getGroupAlias().equals( alias ) ) { if ( tableGroupJoin.getJoinedGroup().getGroupAlias().equals( alias ) ) {
tableGroupJoin.applyPredicate( predicate ); if ( CollectionHelper.isNotEmpty( predicates ) ) {
predicates.forEach( tableGroupJoin::applyPredicate );
}
} }
} ); } );
} } );
);
} }
} }
} }
@ -2319,14 +2329,15 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
this, this,
creationContext creationContext
); );
final FilterPredicate filterPredicate = FilterHelper.createFilterPredicate(
getLoadQueryInfluencers(), ( (Restrictable) entityDescriptor ).applyRestrictions(
(Joinable) entityDescriptor, currentQuerySpec,
tableGroup tableGroup,
true,
loadQueryInfluencers.getEnabledFilters(),
Collections.emptySet(),
getFromClauseAccess()
); );
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 );
@ -3242,14 +3253,15 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
this, this,
creationContext creationContext
); );
final FilterPredicate filterPredicate = FilterHelper.createFilterPredicate(
getLoadQueryInfluencers(), ( (Joinable) pluralAttributeMapping.getCollectionDescriptor() ).applyRestrictions(
(Joinable) pluralAttributeMapping.getCollectionDescriptor(), subQuerySpec,
tableGroup tableGroup,
true,
getLoadQueryInfluencers().getEnabledFilters(),
Collections.emptySet(),
getFromClauseAccess()
); );
if ( filterPredicate != null ) {
subQuerySpec.applyPredicate( filterPredicate );
}
getFromClauseAccess().registerTableGroup( pluralPath.getNavigablePath(), tableGroup ); getFromClauseAccess().registerTableGroup( pluralPath.getNavigablePath(), tableGroup );
registerPluralTableGroupParts( tableGroup ); registerPluralTableGroupParts( tableGroup );
@ -3385,14 +3397,15 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
this, this,
creationContext creationContext
); );
final FilterPredicate filterPredicate = FilterHelper.createFilterPredicate(
getLoadQueryInfluencers(), ( (Joinable) pluralAttributeMapping.getCollectionDescriptor() ).applyRestrictions(
(Joinable) pluralAttributeMapping.getCollectionDescriptor(), subQuerySpec,
tableGroup tableGroup,
true,
getLoadQueryInfluencers().getEnabledFilters(),
Collections.emptySet(),
getFromClauseAccess()
); );
if ( filterPredicate != null ) {
subQuerySpec.applyPredicate( filterPredicate );
}
getFromClauseAccess().registerTableGroup( pluralPartPath.getNavigablePath(), tableGroup ); getFromClauseAccess().registerTableGroup( pluralPartPath.getNavigablePath(), tableGroup );
registerPluralTableGroupParts( tableGroup ); registerPluralTableGroupParts( tableGroup );
@ -5023,14 +5036,15 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
this, this,
creationContext creationContext
); );
final FilterPredicate filterPredicate = FilterHelper.createFilterPredicate(
getLoadQueryInfluencers(), ( (Joinable) pluralAttributeMapping.getCollectionDescriptor() ).applyRestrictions(
(Joinable) pluralAttributeMapping.getCollectionDescriptor(), subQuerySpec,
tableGroup tableGroup,
true,
getLoadQueryInfluencers().getEnabledFilters(),
Collections.emptySet(),
getFromClauseAccess()
); );
if ( filterPredicate != null ) {
subQuerySpec.applyPredicate( filterPredicate );
}
getFromClauseAccess().registerTableGroup( pluralPath.getNavigablePath(), tableGroup ); getFromClauseAccess().registerTableGroup( pluralPath.getNavigablePath(), tableGroup );
registerPluralTableGroupParts( tableGroup ); registerPluralTableGroupParts( tableGroup );
@ -5661,31 +5675,14 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
if ( fetchable instanceof PluralAttributeMapping && fetch.getTiming() == FetchTiming.IMMEDIATE && joined ) { if ( fetchable instanceof PluralAttributeMapping && fetch.getTiming() == FetchTiming.IMMEDIATE && joined ) {
final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) fetchable; final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) fetchable;
final Joinable joinable = pluralAttributeMapping
.getCollectionDescriptor()
.getCollectionType()
.getAssociatedJoinable( getCreationContext().getSessionFactory() );
final TableGroup tableGroup = getFromClauseIndex().getTableGroup( fetchablePath ); final TableGroup tableGroup = getFromClauseIndex().getTableGroup( fetchablePath );
final FilterPredicate collectionFieldFilterPredicate = FilterHelper.createFilterPredicate(
getLoadQueryInfluencers(), ( (Restrictable) pluralAttributeMapping.getCollectionDescriptor() ).applyRestrictions(
joinable, (predicate, partType, sourceType) -> {
tableGroup if ( partType == RestrictionPredicatePartType.COLLECTION ) {
); addCollectionFilterPredicate( tableGroup.getGroupAlias(), predicate );
if ( collectionFieldFilterPredicate != null ) {
if ( collectionFilterPredicates == null ) {
collectionFilterPredicates = new HashMap<>();
} }
collectionFilterPredicates.put( tableGroup.getGroupAlias(), collectionFieldFilterPredicate ); else if ( partType == RestrictionPredicatePartType.MANY_TO_MANY ) {
}
if ( pluralAttributeMapping.getCollectionDescriptor().isManyToMany() ) {
assert joinable instanceof CollectionPersister;
final Predicate manyToManyFilterPredicate = FilterHelper.createManyToManyFilterPredicate(
getLoadQueryInfluencers(),
( CollectionPersister) joinable,
tableGroup
);
if ( manyToManyFilterPredicate != null ) {
final TableGroup parentTableGroup = getFromClauseIndex().getTableGroup( fetchParent.getNavigablePath() ); final TableGroup parentTableGroup = getFromClauseIndex().getTableGroup( fetchParent.getNavigablePath() );
TableGroupJoin pluralTableGroupJoin = null; TableGroupJoin pluralTableGroupJoin = null;
for ( TableGroupJoin nestedTableGroupJoin : parentTableGroup.getTableGroupJoins() ) { for ( TableGroupJoin nestedTableGroupJoin : parentTableGroup.getTableGroupJoins() ) {
@ -5696,9 +5693,18 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
} }
assert pluralTableGroupJoin != null; assert pluralTableGroupJoin != null;
pluralTableGroupJoin.applyPredicate( manyToManyFilterPredicate ); pluralTableGroupJoin.applyPredicate( predicate );
} }
else if ( partType == RestrictionPredicatePartType.ONE_TO_MANY ) {
addCollectionFilterPredicate( tableGroup.getGroupAlias(), predicate );
} }
},
tableGroup,
true,
getLoadQueryInfluencers().getEnabledFilters(),
Collections.emptySet(),
getFromClauseAccess()
);
if ( currentQuerySpec().isRoot() ) { if ( currentQuerySpec().isRoot() ) {
assert tableGroup.getModelPart() == pluralAttributeMapping; assert tableGroup.getModelPart() == pluralAttributeMapping;
@ -5721,6 +5727,18 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
} }
} }
private void addCollectionFilterPredicate(String groupAlias, Predicate predicate) {
final List<Predicate> existing = collectionFilterPredicates.get( groupAlias );
if ( existing != null ) {
existing.add( predicate );
}
else {
final ArrayList<Predicate> list = new ArrayList<>();
list.add( predicate );
collectionFilterPredicates.put( groupAlias, list );
}
}
private void applyOrdering(TableGroup tableGroup, PluralAttributeMapping pluralAttributeMapping) { private void applyOrdering(TableGroup tableGroup, PluralAttributeMapping pluralAttributeMapping) {
if ( pluralAttributeMapping.getOrderByFragment() != null ) { if ( pluralAttributeMapping.getOrderByFragment() != null ) {
applyOrdering( tableGroup, pluralAttributeMapping.getOrderByFragment() ); applyOrdering( tableGroup, pluralAttributeMapping.getOrderByFragment() );

View File

@ -157,6 +157,7 @@ public interface SqlAstWalker {
void visitBetweenPredicate(BetweenPredicate betweenPredicate); void visitBetweenPredicate(BetweenPredicate betweenPredicate);
void visitFilterPredicate(FilterPredicate filterPredicate); void visitFilterPredicate(FilterPredicate filterPredicate);
void visitFilterFragmentPredicate(FilterPredicate.FilterFragmentPredicate fragmentPredicate);
void visitWhereFilterPredicate(WhereFilterPredicate whereFilterPredicate); void visitWhereFilterPredicate(WhereFilterPredicate whereFilterPredicate);

View File

@ -4279,14 +4279,22 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
@Override @Override
public void visitFilterPredicate(FilterPredicate filterPredicate) { public void visitFilterPredicate(FilterPredicate filterPredicate) {
assert StringHelper.isNotEmpty( filterPredicate.getFilterFragment() ); visitJunction( filterPredicate.getFragments() );
appendSql( filterPredicate.getFilterFragment() );
for ( FilterJdbcParameter filterJdbcParameter : filterPredicate.getFilterJdbcParameters() ) { final List<FilterJdbcParameter> parameters = filterPredicate.getParameters();
if ( parameters != null ) {
for ( FilterJdbcParameter filterJdbcParameter : parameters ) {
parameterBinders.add( filterJdbcParameter.getBinder() ); parameterBinders.add( filterJdbcParameter.getBinder() );
jdbcParameters.addParameter( filterJdbcParameter.getParameter() ); jdbcParameters.addParameter( filterJdbcParameter.getParameter() );
filterJdbcParameters.add( filterJdbcParameter ); filterJdbcParameters.add( filterJdbcParameter );
} }
} }
}
@Override
public void visitFilterFragmentPredicate(FilterPredicate.FilterFragmentPredicate fragmentPredicate) {
appendSql( fragmentPredicate.getSqlFragment() );
}
@Override @Override
public void visitWhereFilterPredicate(WhereFilterPredicate whereFilterPredicate) { public void visitWhereFilterPredicate(WhereFilterPredicate whereFilterPredicate) {

View File

@ -447,6 +447,10 @@ public class AbstractSqlAstWalker implements SqlAstWalker {
public void visitFilterPredicate(FilterPredicate filterPredicate) { public void visitFilterPredicate(FilterPredicate filterPredicate) {
} }
@Override
public void visitFilterFragmentPredicate(FilterPredicate.FilterFragmentPredicate fragmentPredicate) {
}
@Override @Override
public void visitWhereFilterPredicate(WhereFilterPredicate whereFilterPredicate) { public void visitWhereFilterPredicate(WhereFilterPredicate whereFilterPredicate) {
} }

View File

@ -6,6 +6,7 @@
*/ */
package org.hibernate.sql.ast.tree.predicate; package org.hibernate.sql.ast.tree.predicate;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.hibernate.internal.FilterJdbcParameter; import org.hibernate.internal.FilterJdbcParameter;
@ -21,17 +22,30 @@ import org.hibernate.sql.ast.SqlAstWalker;
* @author Nathan Xu * @author Nathan Xu
*/ */
public class FilterPredicate implements Predicate { public class FilterPredicate implements Predicate {
private final String filterFragment; private Junction fragments = new Junction();
private final List<FilterJdbcParameter> filterJdbcParameters; private List<FilterJdbcParameter> parameters;
public FilterPredicate(String filterFragment, List<FilterJdbcParameter> filterJdbcParameters) { public FilterPredicate() {
this.filterFragment = filterFragment; }
this.filterJdbcParameters = filterJdbcParameters;
public void applyFragment(FilterFragmentPredicate predicate) {
fragments.add( predicate );
}
public void applyFragment(String sqlFragment) {
fragments.add( new FilterFragmentPredicate( sqlFragment ) );
}
public void applyParameter(FilterJdbcParameter parameter) {
if ( parameters == null ) {
parameters = new ArrayList<>();
}
parameters.add( parameter );
} }
@Override @Override
public boolean isEmpty() { public boolean isEmpty() {
return false; return fragments.isEmpty();
} }
@Override @Override
@ -39,16 +53,43 @@ public class FilterPredicate implements Predicate {
sqlTreeWalker.visitFilterPredicate( this ); sqlTreeWalker.visitFilterPredicate( this );
} }
public String getFilterFragment() { public Junction getFragments() {
return filterFragment; return fragments;
} }
public List<FilterJdbcParameter> getFilterJdbcParameters() { public List<FilterJdbcParameter> getParameters() {
return filterJdbcParameters; return parameters;
} }
@Override @Override
public JdbcMappingContainer getExpressionType() { public JdbcMappingContainer getExpressionType() {
return null; return null;
} }
public static class FilterFragmentPredicate implements Predicate {
private final String sqlFragment;
public FilterFragmentPredicate(String sqlFragment) {
this.sqlFragment = sqlFragment;
}
public String getSqlFragment() {
return sqlFragment;
}
@Override
public void accept(SqlAstWalker sqlTreeWalker) {
sqlTreeWalker.visitFilterFragmentPredicate( this );
}
@Override
public JdbcMappingContainer getExpressionType() {
return null;
}
@Override
public boolean isEmpty() {
return false;
}
}
} }

View File

@ -31,6 +31,10 @@ public class Junction implements Predicate {
private final JdbcMappingContainer expressionType; private final JdbcMappingContainer expressionType;
private final List<Predicate> predicates = new ArrayList<>(); private final List<Predicate> predicates = new ArrayList<>();
public Junction() {
this( Nature.CONJUNCTION );
}
public Junction(Nature nature) { public Junction(Nature nature) {
this( nature, null ); this( nature, null );
} }

View File

@ -11,6 +11,7 @@ import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.hibernate.Filter; import org.hibernate.Filter;
@ -58,6 +59,7 @@ import org.hibernate.persister.walking.spi.CollectionElementDefinition;
import org.hibernate.persister.walking.spi.CollectionIndexDefinition; import org.hibernate.persister.walking.spi.CollectionIndexDefinition;
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition; import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.predicate.FilterPredicate;
import org.hibernate.tuple.entity.BytecodeEnhancementMetadataNonPojoImpl; import org.hibernate.tuple.entity.BytecodeEnhancementMetadataNonPojoImpl;
import org.hibernate.tuple.entity.EntityMetamodel; import org.hibernate.tuple.entity.EntityMetamodel;
import org.hibernate.tuple.entity.EntityTuplizer; import org.hibernate.tuple.entity.EntityTuplizer;
@ -703,6 +705,11 @@ public class GoofyPersisterClassProvider implements PersisterClassResolver {
public JavaType getMappedJavaTypeDescriptor() { public JavaType getMappedJavaTypeDescriptor() {
return null; return null;
} }
@Override
public FilterPredicate generateFilterPredicate(TableGroup tableGroup, boolean useQualifier, Set<String> treatAsDeclarations, Map<String, Filter> enabledFilters) {
return null;
}
} }
public static class NoopCollectionPersister implements CollectionPersister { public static class NoopCollectionPersister implements CollectionPersister {

View File

@ -12,10 +12,12 @@ import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
import jakarta.persistence.EntityManagerFactory; import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.PersistenceException; import jakarta.persistence.PersistenceException;
import org.hibernate.Filter;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.LockOptions; import org.hibernate.LockOptions;
@ -58,6 +60,8 @@ import org.hibernate.persister.spi.PersisterClassResolver;
import org.hibernate.persister.spi.PersisterCreationContext; import org.hibernate.persister.spi.PersisterCreationContext;
import org.hibernate.persister.walking.spi.AttributeDefinition; import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition; import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.predicate.FilterPredicate;
import org.hibernate.tuple.entity.BytecodeEnhancementMetadataNonPojoImpl; import org.hibernate.tuple.entity.BytecodeEnhancementMetadataNonPojoImpl;
import org.hibernate.tuple.entity.EntityMetamodel; import org.hibernate.tuple.entity.EntityMetamodel;
import org.hibernate.tuple.entity.EntityTuplizer; import org.hibernate.tuple.entity.EntityTuplizer;
@ -717,6 +721,11 @@ public class PersisterClassProviderTest {
public JavaType getMappedJavaTypeDescriptor() { public JavaType getMappedJavaTypeDescriptor() {
return null; return null;
} }
@Override
public FilterPredicate generateFilterPredicate(TableGroup tableGroup, boolean useQualifier, Set<String> treatAsDeclarations, Map<String, Filter> enabledFilters) {
return null;
}
} }
public static class GoofyException extends RuntimeException { public static class GoofyException extends RuntimeException {

View File

@ -13,8 +13,10 @@ import java.util.Hashtable;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.hibernate.Filter;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.LockOptions; import org.hibernate.LockOptions;
@ -54,6 +56,8 @@ import org.hibernate.loader.ast.spi.MultiIdLoadOptions;
import org.hibernate.persister.spi.PersisterCreationContext; import org.hibernate.persister.spi.PersisterCreationContext;
import org.hibernate.persister.walking.spi.AttributeDefinition; import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition; import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.predicate.FilterPredicate;
import org.hibernate.tuple.entity.BytecodeEnhancementMetadataNonPojoImpl; import org.hibernate.tuple.entity.BytecodeEnhancementMetadataNonPojoImpl;
import org.hibernate.tuple.entity.EntityMetamodel; import org.hibernate.tuple.entity.EntityMetamodel;
import org.hibernate.tuple.entity.EntityTuplizer; import org.hibernate.tuple.entity.EntityTuplizer;
@ -818,4 +822,9 @@ public class CustomPersister implements EntityPersister {
public JavaType getMappedJavaTypeDescriptor() { public JavaType getMappedJavaTypeDescriptor() {
return null; return null;
} }
@Override
public FilterPredicate generateFilterPredicate(TableGroup tableGroup, boolean useQualifier, Set<String> treatAsDeclarations, Map<String, Filter> enabledFilters) {
return null;
}
} }