HHH-15133 - Use specified result-type to better infer "shape" of query results with implicit selections

Alternate solution for de-duplication handling
This commit is contained in:
Steve Ebersole 2022-03-29 17:30:25 -05:00
parent c033b9aa5f
commit 5b0c49e6a2
8 changed files with 21 additions and 92 deletions

View File

@ -211,11 +211,6 @@ public class LoaderSqlAstCreationState
return null;
}
@Override
public Boolean isDeDuplicationEnabled() {
return false;
}
@Override
public Boolean isResultCachingEnabled() {
return false;

View File

@ -43,7 +43,6 @@ public class QueryOptionsImpl implements MutableQueryOptions, AppliedGraph {
private TupleTransformer tupleTransformer;
private ResultListTransformer resultListTransformer;
private Boolean deDupEnabled;
private RootGraphImplementor<?> rootGraph;
private GraphSemantic graphSemantic;
@ -161,15 +160,6 @@ public class QueryOptionsImpl implements MutableQueryOptions, AppliedGraph {
return resultListTransformer;
}
@Override
public Boolean isDeDuplicationEnabled() {
return deDupEnabled;
}
public void setDeDuplicationEnabled(boolean enabled) {
this.deDupEnabled = enabled;
}
public void setResultCacheRegionName(String resultCacheRegionName) {
this.resultCacheRegionName = resultCacheRegionName;
}

View File

@ -58,11 +58,6 @@ public class DelegatingQueryOptions implements QueryOptions {
return queryOptions.getResultListTransformer();
}
@Override
public Boolean isDeDuplicationEnabled() {
return queryOptions.isDeDuplicationEnabled();
}
@Override
public Boolean isResultCachingEnabled() {
return queryOptions.isResultCachingEnabled();

View File

@ -62,13 +62,6 @@ public interface QueryOptions {
*/
ResultListTransformer<?> getResultListTransformer();
Boolean isDeDuplicationEnabled();
default boolean shouldApplyDeDuplication() {
final Boolean setting = isDeDuplicationEnabled();
return setting != null && setting;
}
/**
* Should results from the query be cached?
*

View File

@ -80,11 +80,6 @@ public abstract class QueryOptionsAdapter implements QueryOptions {
return null;
}
@Override
public Boolean isDeDuplicationEnabled() {
return null;
}
@Override
public String getResultCacheRegionName() {
return null;

View File

@ -122,9 +122,7 @@ public class ConcreteSqmSelectQueryPlan<R> implements SelectQueryPlan<R> {
}
},
rowTransformer,
queryOptions.shouldApplyDeDuplication()
? ListResultsConsumer.UniqueSemantic.FILTER
: ListResultsConsumer.UniqueSemantic.NONE
ListResultsConsumer.UniqueSemantic.ALLOW
);
}
finally {

View File

@ -217,7 +217,6 @@ public class JdbcSelectExecutorStandardImpl implements JdbcSelectExecutor {
final AppliedGraph appliedGraph = queryOptions.getAppliedGraph();
final TupleTransformer<?> tupleTransformer = queryOptions.getTupleTransformer();
final ResultListTransformer<?> resultListTransformer = queryOptions.getResultListTransformer();
final Boolean deDuplicationEnabled = queryOptions.isDeDuplicationEnabled();
final Boolean resultCachingEnabled = queryOptions.isResultCachingEnabled();
final CacheRetrieveMode cacheRetrieveMode = queryOptions.getCacheRetrieveMode();
final CacheStoreMode cacheStoreMode = queryOptions.getCacheStoreMode();
@ -263,11 +262,6 @@ public class JdbcSelectExecutorStandardImpl implements JdbcSelectExecutor {
return resultListTransformer;
}
@Override
public Boolean isDeDuplicationEnabled() {
return deDuplicationEnabled;
}
@Override
public Boolean isResultCachingEnabled() {
return resultCachingEnabled;

View File

@ -14,8 +14,6 @@ import org.hibernate.HibernateException;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.query.ResultListTransformer;
import org.hibernate.query.TupleTransformer;
import org.hibernate.query.TypedTupleTransformer;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.sql.results.internal.RowProcessingStateStandardImpl;
import org.hibernate.sql.results.jdbc.internal.JdbcValuesSourceProcessingStateStandardImpl;
@ -33,6 +31,7 @@ import org.hibernate.type.spi.TypeConfiguration;
*/
public class ListResultsConsumer<R> implements ResultsConsumer<List<R>, R> {
private static final ListResultsConsumer<?> NEVER_DE_DUP_CONSUMER = new ListResultsConsumer<>( UniqueSemantic.NEVER );
private static final ListResultsConsumer<?> ALLOW_DE_DUP_CONSUMER = new ListResultsConsumer<>( UniqueSemantic.ALLOW );
private static final ListResultsConsumer<?> IGNORE_DUP_CONSUMER = new ListResultsConsumer<>( UniqueSemantic.NONE );
private static final ListResultsConsumer<?> DE_DUP_CONSUMER = new ListResultsConsumer<>( UniqueSemantic.FILTER );
private static final ListResultsConsumer<?> ERROR_DUP_CONSUMER = new ListResultsConsumer<>( UniqueSemantic.ASSERT );
@ -49,6 +48,9 @@ public class ListResultsConsumer<R> implements ResultsConsumer<List<R>, R> {
case NEVER: {
return (ListResultsConsumer<R>) NEVER_DE_DUP_CONSUMER;
}
case ALLOW: {
return (ListResultsConsumer<R>) ALLOW_DE_DUP_CONSUMER;
}
default: {
return (ListResultsConsumer<R>) IGNORE_DUP_CONSUMER;
}
@ -78,7 +80,12 @@ public class ListResultsConsumer<R> implements ResultsConsumer<List<R>, R> {
* Never apply unique handling. E.g. for NativeQuery. Whereas {@link #NONE} can be adjusted,
* NEVER will never apply unique handling
*/
NEVER
NEVER,
/**
* De-duplication is allowed if the query and result type allow
*/
ALLOW
}
private final UniqueSemantic uniqueSemantic;
@ -108,7 +115,6 @@ public class ListResultsConsumer<R> implements ResultsConsumer<List<R>, R> {
RowReader<R> rowReader) {
final PersistenceContext persistenceContext = session.getPersistenceContext();
final TypeConfiguration typeConfiguration = session.getTypeConfiguration();
final JavaTypeRegistry javaTypeRegistry = typeConfiguration.getJavaTypeRegistry();
final QueryOptions queryOptions = rowProcessingState.getQueryOptions();
RuntimeException ex = null;
@ -117,58 +123,21 @@ public class ListResultsConsumer<R> implements ResultsConsumer<List<R>, R> {
final List<R> results = new ArrayList<>();
final JavaType<R> domainResultJavaType;
final ResultHandler<R> resultHandlerToUse;
final TupleTransformer<?> tupleTransformer = queryOptions.getTupleTransformer();
if ( tupleTransformer instanceof TypedTupleTransformer ) {
//noinspection unchecked
final TypedTupleTransformer<R> typedTupleTransformer = (TypedTupleTransformer<R>) tupleTransformer;
domainResultJavaType = javaTypeRegistry.resolveDescriptor( typedTupleTransformer.getTransformedType() );
if ( uniqueSemantic == UniqueSemantic.NEVER ) {
resultHandlerToUse = this.resultHandler;
}
else if ( queryOptions.shouldApplyDeDuplication() ) {
resultHandlerToUse = ListResultsConsumer::deDuplicationHandling;
}
else if ( domainResultJavaType instanceof EntityJavaType ) {
resultHandlerToUse = ListResultsConsumer::deDuplicationHandling;
}
else {
resultHandlerToUse = this.resultHandler;
}
}
else {
domainResultJavaType = resolveDomainResultJavaType(
final JavaType<R> domainResultJavaType = resolveDomainResultJavaType(
rowReader.getDomainResultResultJavaType(),
rowReader.getResultJavaTypes(),
typeConfiguration
);
if ( uniqueSemantic == UniqueSemantic.NEVER ) {
resultHandlerToUse = this.resultHandler;
}
else if ( queryOptions.shouldApplyDeDuplication() ) {
resultHandlerToUse = ListResultsConsumer::deDuplicationHandling;
}
else {
if ( uniqueSemantic == UniqueSemantic.ASSERT ) {
if ( rowProcessingState.hasCollectionInitializers ) {
final ResultHandler<R> resultHandlerToUse;
if ( uniqueSemantic == UniqueSemantic.ALLOW
&& domainResultJavaType instanceof EntityJavaType ) {
resultHandlerToUse = ListResultsConsumer::deDuplicationHandling;
}
else {
resultHandlerToUse = this.resultHandler;
}
}
else if ( domainResultJavaType instanceof EntityJavaType ) {
resultHandlerToUse = ListResultsConsumer::deDuplicationHandling;
}
else {
resultHandlerToUse = this.resultHandler;
}
}
}
while ( rowProcessingState.next() ) {
final R row = rowReader.readRow( rowProcessingState, processingOptions );