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-18 04:26:38 -06:00
parent 98c9cf136c
commit 335a4d62e3
9 changed files with 23 additions and 293 deletions

View File

@ -916,10 +916,6 @@ public abstract class AbstractCollectionPersister
return collectionType;
}
protected String getSQLWhereString(String alias) {
return StringHelper.replace( sqlWhereStringTemplate, Template.TEMPLATE, alias );
}
@Override
public String getSQLOrderByString(String alias) {
// return hasOrdering()
@ -1877,23 +1873,21 @@ public abstract class AbstractCollectionPersister
alias = tableReference.getTableExpression();
}
applyLegacyNamedFilterFragment( predicateConsumer, alias, tableGroup, creationState );
applyWhereFragments( predicateConsumer, alias, tableGroup, creationState );
}
/**
* Replaces {@link #filterFragment(String)} and {@link #filterFragment(String, Set)}
*
* @todo (6.0) - drop these 2 ^^
*/
protected void applyLegacyNamedFilterFragment(
protected void applyWhereFragments(
Consumer<Predicate> predicateConsumer,
String alias,
TableGroup tableGroup,
SqlAstCreationState astCreationState) {
applyWhereRestriction( sqlWhereStringTemplate, alias, predicateConsumer );
applyWhereFragments( predicateConsumer, alias, sqlWhereStringTemplate );
}
private static void applyWhereRestriction(String template, String alias, Consumer<Predicate> predicateConsumer) {
/**
* Applies all defined {@link org.hibernate.annotations.Where}
*/
private static void applyWhereFragments(Consumer<Predicate> predicateConsumer, String alias, String template) {
if ( template == null ) {
return;
}
@ -1906,14 +1900,6 @@ public abstract class AbstractCollectionPersister
predicateConsumer.accept( new SqlFragmentPredicate( fragment ) );
}
protected String filterFragment(String alias) throws MappingException {
return hasWhere() ? getSQLWhereString( alias ) : "";
}
protected String filterFragment(String alias, Set<String> treatAsDeclarations) throws MappingException {
return hasWhere() ? getSQLWhereString( alias ) : "";
}
@Override
public void applyFilterRestrictions(Consumer<Predicate> predicateConsumer, TableGroup tableGroup, boolean useQualifier, Map<String, Filter> enabledFilters, SqlAstCreationState creationState) {
if ( filterHelper != null ) {
@ -1954,7 +1940,7 @@ public abstract class AbstractCollectionPersister
alias = tableReference.getTableExpression();
}
applyWhereRestriction( manyToManyWhereTemplate, alias, predicateConsumer );
applyWhereFragments( predicateConsumer, alias, manyToManyWhereTemplate );
}
}
@ -2094,77 +2080,6 @@ public abstract class AbstractCollectionPersister
}
@Override
public String filterFragment(
String alias,
Map<String, Filter> enabledFilters,
Set<String> treatAsDeclarations) {
final StringBuilder sessionFilterFragment = new StringBuilder();
if ( filterHelper != null ) {
filterHelper.render( sessionFilterFragment, getFilterAliasGenerator(alias), enabledFilters );
}
final String filterFragment = filterFragment( alias, treatAsDeclarations );
if ( sessionFilterFragment.length() != 0
&& !filterFragment.isEmpty() ) {
sessionFilterFragment.append( " and " );
}
return sessionFilterFragment.append( filterFragment ).toString();
}
@Override
public String filterFragment(
TableGroup tableGroup,
Map<String, Filter> enabledFilters,
Set<String> treatAsDeclarations,
boolean useIdentificationVariable) {
TableReference tableReference;
if ( isManyToMany() ) {
// if filtering on many-to-many element were intended, getManyToManyFilterFragment() should have been chosen
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 ( useIdentificationVariable && tableReference.getIdentificationVariable() != null ) {
alias = tableReference.getIdentificationVariable();
}
else {
alias = tableReference.getTableExpression();
}
final StringBuilder sessionFilterFragment = new StringBuilder();
if ( filterHelper != null ) {
filterHelper.render( sessionFilterFragment, getFilterAliasGenerator( tableGroup ), enabledFilters );
}
final String filterFragment = filterFragment( alias, treatAsDeclarations );
if ( sessionFilterFragment.length() != 0 && !filterFragment.isEmpty() ) {
sessionFilterFragment.append( " and " );
}
return sessionFilterFragment.append( filterFragment ).toString();
}
@Override
public String oneToManyFilterFragment(String alias) throws MappingException {
return "";
}
@Override
public String oneToManyFilterFragment(String alias, Set<String> treatAsDeclarations) {
return oneToManyFilterFragment( alias );
}
protected boolean isInsertCallable() {
return insertCallable;
}

View File

@ -9,7 +9,6 @@ package org.hibernate.persister.collection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.Set;
import java.util.function.Consumer;
import org.hibernate.HibernateException;
@ -20,7 +19,6 @@ import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.FilterAliasGenerator;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.jdbc.Expectation;
import org.hibernate.jdbc.Expectations;
@ -199,8 +197,8 @@ public class OneToManyPersister extends AbstractCollectionPersister {
}
private void writeIndex(
PersistentCollection collection,
Iterator entries,
PersistentCollection<?> collection,
Iterator<?> entries,
Object id,
boolean resetIndex,
SharedSessionContractImplementor session) {
@ -342,7 +340,7 @@ public class OneToManyPersister extends AbstractCollectionPersister {
// update removed rows fks to null
try {
int i = 0;
Iterator entries = collection.entries( this );
Iterator<?> entries = collection.entries( this );
int offset = 1;
while ( entries.hasNext() ) {
Object entry = entries.next();
@ -413,7 +411,7 @@ public class OneToManyPersister extends AbstractCollectionPersister {
// now update all changed or added rows fks
try {
int i = 0;
Iterator entries = collection.entries( this );
Iterator<?> entries = collection.entries( this );
while ( entries.hasNext() ) {
Object entry = entries.next();
int offset = 1;
@ -486,12 +484,21 @@ public class OneToManyPersister extends AbstractCollectionPersister {
return ( (Joinable) getElementPersister() ).getTableName();
}
protected void applyLegacyNamedFilterFragment(
@Override
public void applyWhereRestrictions(
Consumer<Predicate> predicateConsumer,
TableGroup tableGroup,
boolean useQualifier,
SqlAstCreationState creationState) {
super.applyWhereRestrictions( predicateConsumer, tableGroup, useQualifier, creationState );
}
protected void applyWhereFragments(
Consumer<Predicate> predicateConsumer,
String alias,
TableGroup tableGroup,
SqlAstCreationState astCreationState) {
super.applyLegacyNamedFilterFragment( predicateConsumer, alias, tableGroup, astCreationState );
super.applyWhereFragments( predicateConsumer, alias, tableGroup, astCreationState );
getElementPersisterInternal().applyDiscriminator(
predicateConsumer,
@ -501,31 +508,6 @@ public class OneToManyPersister extends AbstractCollectionPersister {
);
}
@Override
public String filterFragment(String alias) throws MappingException {
String result = super.filterFragment( alias );
if ( getElementPersister() instanceof Joinable ) {
result += ( (Joinable) getElementPersister() ).oneToManyFilterFragment( alias );
}
return result;
}
@Override
protected String filterFragment(String alias, Set<String> treatAsDeclarations) throws MappingException {
String result = super.filterFragment( alias );
if ( getElementPersister() instanceof Joinable ) {
final String associationFilter = ( (Joinable) getElementPersister() ).oneToManyFilterFragment( alias, treatAsDeclarations );
if ( StringHelper.isEmpty( result ) ) {
result = associationFilter;
}
else if ( StringHelper.isNotEmpty( associationFilter ) ) {
result += " and " + associationFilter;
}
}
return result;
}
@Override
public FilterAliasGenerator getFilterAliasGenerator(String rootAlias) {
return getElementPersister().getFilterAliasGenerator( rootAlias );

View File

@ -232,11 +232,9 @@ import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.from.StandardTableGroup;
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.predicate.ComparisonPredicate;
import org.hibernate.sql.ast.tree.predicate.FilterPredicate;
import org.hibernate.sql.ast.tree.predicate.Junction;
import org.hibernate.sql.ast.tree.predicate.Predicate;
import org.hibernate.sql.ast.tree.select.QuerySpec;
@ -4044,55 +4042,6 @@ public abstract class AbstractEntityPersister
protected abstract String filterFragment(String alias, Set<String> treatAsDeclarations);
@Override
public String filterFragment(String alias, Map<String, Filter> enabledFilters, Set<String> treatAsDeclarations) {
if ( filterHelper == null ) {
return "";
}
final StringBuilder sessionFilterFragment = new StringBuilder();
if ( filterHelper != null ) {
filterHelper.render( sessionFilterFragment, alias == null ? null : getFilterAliasGenerator( alias ), enabledFilters );
}
final String filterFragment = filterFragment( alias, treatAsDeclarations );
if ( sessionFilterFragment.length() != 0 && !filterFragment.isEmpty() ) {
sessionFilterFragment.append( " and " );
}
return sessionFilterFragment.append( filterFragment ).toString();
}
@Override
public String filterFragment(
TableGroup tableGroup,
Map<String, Filter> enabledFilters,
Set<String> treatAsDeclarations,
boolean useIdentificationVariable) {
if ( filterHelper == null ) {
return null;
}
final String alias;
if ( tableGroup == null ) {
alias = null;
}
else if ( useIdentificationVariable && tableGroup.getPrimaryTableReference().getIdentificationVariable() != null ) {
alias = tableGroup.getPrimaryTableReference().getIdentificationVariable();
}
else {
alias = tableGroup.getPrimaryTableReference().getTableExpression();
}
final StringBuilder sessionFilterFragment = new StringBuilder();
if ( filterHelper != null ) {
filterHelper.render( sessionFilterFragment, !useIdentificationVariable || tableGroup == null ? null : getFilterAliasGenerator( tableGroup ), enabledFilters );
}
final String filterFragment = filterFragment( alias, treatAsDeclarations );
if ( sessionFilterFragment.length() != 0 && !filterFragment.isEmpty() ) {
sessionFilterFragment.append( " and " );
}
return sessionFilterFragment.append( filterFragment ).toString();
}
public String generateWhereConditionAlias(String alias) {
return alias;
}
@ -4101,15 +4050,6 @@ public abstract class AbstractEntityPersister
return rootAlias;
}
public String oneToManyFilterFragment(String alias) throws MappingException {
return "";
}
@Override
public String oneToManyFilterFragment(String alias, Set<String> treatAsDeclarations) {
return oneToManyFilterFragment( alias );
}
protected boolean isSubclassTableLazy(int j) {
return false;
}

View File

@ -6,14 +6,7 @@
*/
package org.hibernate.persister.entity;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import org.hibernate.Filter;
import org.hibernate.MappingException;
import org.hibernate.metamodel.mapping.Restrictable;
import org.hibernate.sql.ast.tree.from.TableGroup;
/**
* Anything that can be loaded by outer join - namely
@ -38,28 +31,6 @@ public interface Joinable extends Restrictable {
*/
public String[] getKeyColumnNames();
/**
* Get the where clause filter, given a query alias and considering enabled session filters
*/
public default String filterFragment(String alias, Map<String, Filter> enabledFilters) throws MappingException {
return filterFragment( alias, enabledFilters, Collections.emptySet() );
}
/**
* Get the where clause filter, given a query alias and considering enabled session filters
*/
public String filterFragment(String alias, Map<String, Filter> enabledFilters, Set<String> treatAsDeclarations) throws MappingException;
public String filterFragment(
TableGroup tableGroup,
Map<String, Filter> enabledFilters,
Set<String> treatAsDeclarations,
boolean useIdentificationVariable) throws MappingException;
public String oneToManyFilterFragment(String alias) throws MappingException;
public String oneToManyFilterFragment(String alias, Set<String> treatAsDeclarations);
/**
* Is this instance actually a CollectionPersister?
*/

View File

@ -22,7 +22,6 @@ import org.hibernate.boot.model.relational.Database;
import org.hibernate.cache.spi.access.EntityDataAccess;
import org.hibernate.cache.spi.access.NaturalIdDataAccess;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.DynamicFilterAliasGenerator;
@ -592,19 +591,6 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
return discriminatorFilterFragment( alias, null );
}
public String oneToManyFilterFragment(String alias) throws MappingException {
return forceDiscriminator
? discriminatorFilterFragment( alias, null )
: "";
}
@Override
public String oneToManyFilterFragment(String alias, Set<String> treatAsDeclarations) {
return needsDiscriminator()
? discriminatorFilterFragment( alias, treatAsDeclarations )
: "";
}
@Override
protected String filterFragment(String alias, Set<String> treatAsDeclarations) {
if ( hasWhere() ) {

View File

@ -14,7 +14,6 @@ import java.sql.SQLException;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import org.hibernate.EntityNameResolver;
import org.hibernate.FetchMode;
@ -454,20 +453,6 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
throw new UnsupportedOperationException("any types do not have a unique referenced persister");
}
@Override
public String getOnCondition(String alias, SessionFactoryImplementor factory, Map enabledFilters) {
throw new UnsupportedOperationException();
}
@Override
public String getOnCondition(
String alias,
SessionFactoryImplementor factory,
Map enabledFilters,
Set<String> treatAsDeclarations) {
throw new UnsupportedOperationException();
}
/**
* Used to externalize discrimination per a given identifier. For example, when writing to
* second level cache we write the discrimination resolved concrete type for each entity written.

View File

@ -57,19 +57,6 @@ public interface AssociationType extends Type {
*/
String getAssociatedEntityName(SessionFactoryImplementor factory) throws MappingException;
/**
* Get the "filtering" SQL fragment that is applied in the
* SQL on clause, in addition to the usual join condition
*/
String getOnCondition(String alias, SessionFactoryImplementor factory, Map enabledFilters)
throws MappingException;
/**
* Get the "filtering" SQL fragment that is applied in the
* SQL on clause, in addition to the usual join condition
*/
String getOnCondition(String alias, SessionFactoryImplementor factory, Map enabledFilters, Set<String> treatAsDeclarations);
/**
* Do we dirty check this association, even when there are
* no columns to be updated?

View File

@ -15,7 +15,6 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
@ -744,21 +743,6 @@ public abstract class CollectionType extends AbstractType implements Association
return getClass().getName() + '(' + getRole() + ')';
}
@Override
public String getOnCondition(String alias, SessionFactoryImplementor factory, Map enabledFilters)
throws MappingException {
return getAssociatedJoinable( factory ).filterFragment( alias, enabledFilters );
}
@Override
public String getOnCondition(
String alias,
SessionFactoryImplementor factory,
Map enabledFilters,
Set<String> treatAsDeclarations) {
return getAssociatedJoinable( factory ).filterFragment( alias, enabledFilters, treatAsDeclarations );
}
/**
* instantiate a collection wrapper (called when loading an object)
*

View File

@ -9,7 +9,6 @@ package org.hibernate.type;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Map;
import java.util.Set;
import org.hibernate.AssertionFailure;
import org.hibernate.HibernateException;
@ -380,25 +379,6 @@ public abstract class EntityType extends AbstractType implements AssociationType
.isEqual( xid, yid, factory );
}
@Override
public String getOnCondition(String alias, SessionFactoryImplementor factory, Map enabledFilters) {
return getOnCondition( alias, factory, enabledFilters, null );
}
@Override
public String getOnCondition(
String alias,
SessionFactoryImplementor factory,
Map enabledFilters,
Set<String> treatAsDeclarations) {
if ( isReferenceToPrimaryKey() && ( treatAsDeclarations == null || treatAsDeclarations.isEmpty() ) ) {
return "";
}
else {
return getAssociatedJoinable( factory ).filterFragment( alias, enabledFilters, treatAsDeclarations );
}
}
/**
* Resolve an identifier or unique key value
*/