Pass UniqueSemantic enum to SingleIdLoadPlan#load method and refactoring of ListResultConsumer#consume() method

This commit is contained in:
Andrea Boriero 2021-06-04 14:34:30 +02:00
parent d1bc4e6a33
commit d640662435
19 changed files with 70 additions and 81 deletions

View File

@ -53,6 +53,7 @@ import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.sql.exec.spi.JdbcSelect;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.Fetch;
import org.hibernate.sql.results.spi.ListResultsConsumer;
import org.hibernate.stat.spi.StatisticsImplementor;
/**
@ -233,7 +234,7 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
}
},
row -> (L) row[0],
true
ListResultsConsumer.UniqueSemantic.FILTER
);
if ( results.size() > 1 ) {
@ -414,7 +415,7 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
assert row.length == 1;
return row[0];
},
true
ListResultsConsumer.UniqueSemantic.FILTER
);
if ( results.isEmpty() ) {

View File

@ -35,6 +35,7 @@ import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.sql.exec.spi.JdbcSelect;
import org.hibernate.sql.results.internal.RowTransformerPassThruImpl;
import org.hibernate.sql.results.spi.ListResultsConsumer;
/**
* @author Andrea Boriero
@ -165,7 +166,7 @@ public class CollectionElementLoaderByIndex implements Loader {
}
},
RowTransformerPassThruImpl.instance(),
true
ListResultsConsumer.UniqueSemantic.FILTER
);
if ( list.isEmpty() ) {

View File

@ -32,6 +32,7 @@ import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.sql.exec.spi.JdbcSelect;
import org.hibernate.sql.results.internal.RowTransformerPassThruImpl;
import org.hibernate.sql.results.spi.ListResultsConsumer;
import org.jboss.logging.Logger;
@ -202,7 +203,7 @@ public class CollectionLoaderBatchKey implements CollectionLoader {
}
},
RowTransformerPassThruImpl.instance(),
true
ListResultsConsumer.UniqueSemantic.FILTER
);

View File

@ -31,6 +31,7 @@ import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.sql.exec.spi.JdbcSelect;
import org.hibernate.sql.results.internal.RowTransformerPassThruImpl;
import org.hibernate.sql.results.spi.ListResultsConsumer;
/**
* Main implementation of CollectionLoader for handling a load of a single collection-key
@ -135,7 +136,7 @@ public class CollectionLoaderSingleKey implements CollectionLoader {
}
},
RowTransformerPassThruImpl.instance(),
true
ListResultsConsumer.UniqueSemantic.FILTER
);
return session.getPersistenceContext().getCollection( collectionKey );

View File

@ -25,6 +25,7 @@ import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.exec.spi.JdbcSelect;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.internal.RowTransformerPassThruImpl;
import org.hibernate.sql.results.spi.ListResultsConsumer;
/**
* A one-time use CollectionLoader for applying a sub-select fetch
@ -96,7 +97,7 @@ public class CollectionLoaderSubSelectFetch implements CollectionLoader {
}
},
RowTransformerPassThruImpl.instance(),
true
ListResultsConsumer.UniqueSemantic.FILTER
);
final CollectionKey collectionKey = new CollectionKey( attributeMapping.getCollectionDescriptor(), triggerKey );

View File

@ -46,6 +46,7 @@ import org.hibernate.sql.exec.spi.JdbcSelect;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.basic.BasicResult;
import org.hibernate.sql.results.internal.RowTransformerDatabaseSnapshotImpl;
import org.hibernate.sql.results.spi.ListResultsConsumer;
import org.hibernate.type.IntegerType;
import org.jboss.logging.Logger;
@ -229,7 +230,7 @@ class DatabaseSnapshotExecutor {
}
},
RowTransformerDatabaseSnapshotImpl.instance(),
true
ListResultsConsumer.UniqueSemantic.FILTER
);
final int size = list.size();

View File

@ -45,6 +45,7 @@ import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.sql.exec.spi.JdbcSelect;
import org.hibernate.sql.results.graph.entity.LoadingEntityEntry;
import org.hibernate.sql.results.internal.RowTransformerPassThruImpl;
import org.hibernate.sql.results.spi.ListResultsConsumer;
import org.jboss.logging.Logger;
@ -321,7 +322,7 @@ public class MultiIdLoaderStandard<T> implements MultiIdEntityLoader<T> {
}
},
RowTransformerPassThruImpl.instance(),
true
ListResultsConsumer.UniqueSemantic.FILTER
);
}

View File

@ -34,6 +34,7 @@ import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.sql.exec.spi.JdbcSelect;
import org.hibernate.sql.results.graph.entity.LoadingEntityEntry;
import org.hibernate.sql.results.internal.RowTransformerPassThruImpl;
import org.hibernate.sql.results.spi.ListResultsConsumer;
/**
* Batch support for natural-id multi loading
@ -190,7 +191,7 @@ public class MultiNaturalIdLoadingBatcher {
}
},
RowTransformerPassThruImpl.instance(),
true
ListResultsConsumer.UniqueSemantic.FILTER
);
}
}

View File

@ -41,6 +41,7 @@ import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.exec.spi.JdbcParameterBinding;
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.sql.exec.spi.JdbcSelect;
import org.hibernate.sql.results.spi.ListResultsConsumer;
/**
* NaturalIdLoader for simple natural-ids
@ -181,7 +182,7 @@ public class SimpleNaturalIdLoader<T> extends AbstractNaturalIdLoader<T> {
}
},
row -> row[0],
true
ListResultsConsumer.UniqueSemantic.FILTER
);
if ( results.size() > 1 ) {

View File

@ -32,6 +32,7 @@ import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.sql.exec.spi.JdbcSelect;
import org.hibernate.sql.results.internal.RowTransformerPassThruImpl;
import org.hibernate.sql.results.spi.ListResultsConsumer;
import org.jboss.logging.Logger;
@ -147,7 +148,7 @@ public class SingleIdEntityLoaderDynamicBatch<T> extends SingleIdEntityLoaderSup
}
},
RowTransformerPassThruImpl.instance(),
true
ListResultsConsumer.UniqueSemantic.FILTER
);
//noinspection ForLoopReplaceableByForEach

View File

@ -31,6 +31,7 @@ import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.sql.exec.spi.JdbcSelect;
import org.hibernate.sql.results.internal.RowTransformerPassThruImpl;
import org.hibernate.sql.results.spi.ListResultsConsumer;
/**
* todo (6.0) : this can generically define a load-by-uk as well. only the SQL AST and `restrictivePart` vary and they are passed as ctor args
@ -154,8 +155,7 @@ public class SingleIdLoadPlan<T> implements SingleEntityLoadPlan {
}
},
RowTransformerPassThruImpl.instance(),
true,
singleResultExpected
singleResultExpected ? ListResultsConsumer.UniqueSemantic.ASSERT : ListResultsConsumer.UniqueSemantic.FILTER
);
if ( list.isEmpty() ) {

View File

@ -34,6 +34,7 @@ import org.hibernate.sql.exec.spi.Callback;
import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.sql.exec.spi.JdbcSelect;
import org.hibernate.sql.results.spi.ListResultsConsumer;
/**
* @author Steve Ebersole
@ -127,7 +128,7 @@ public class SingleUniqueKeyEntityLoaderStandard<T> implements SingleUniqueKeyEn
}
},
row -> row[0],
true
ListResultsConsumer.UniqueSemantic.FILTER
);
switch ( list.size() ) {
@ -204,7 +205,7 @@ public class SingleUniqueKeyEntityLoaderStandard<T> implements SingleUniqueKeyEn
}
},
row -> row[0],
true
ListResultsConsumer.UniqueSemantic.FILTER
);
assert list.size() == 1;

View File

@ -35,6 +35,7 @@ import org.hibernate.sql.exec.spi.JdbcSelect;
import org.hibernate.sql.exec.spi.JdbcSelectExecutor;
import org.hibernate.sql.results.internal.RowTransformerPassThruImpl;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMappingProducer;
import org.hibernate.sql.results.spi.ListResultsConsumer;
import org.hibernate.sql.results.spi.RowTransformer;
import org.hibernate.type.StandardBasicTypes;
@ -135,7 +136,7 @@ public class NativeSelectQueryPlanImpl<R> implements NativeSelectQueryPlan<R> {
jdbcParameterBindings,
executionContext,
rowTransformer,
false
ListResultsConsumer.UniqueSemantic.NONE
);
}

View File

@ -47,6 +47,7 @@ import org.hibernate.sql.results.internal.RowTransformerPassThruImpl;
import org.hibernate.sql.results.internal.RowTransformerSingularReturnImpl;
import org.hibernate.sql.results.internal.RowTransformerTupleTransformerAdapter;
import org.hibernate.sql.results.internal.TupleMetadata;
import org.hibernate.sql.results.spi.ListResultsConsumer;
import org.hibernate.sql.results.spi.RowTransformer;
/**
@ -85,7 +86,7 @@ public class ConcreteSqmSelectQueryPlan<R> implements SelectQueryPlan<R> {
jdbcParameterBindings,
SqlOmittingQueryOptions.omitSqlQueryOptions( executionContext, jdbcSelect ),
rowTransformer,
true
ListResultsConsumer.UniqueSemantic.FILTER
);
}
finally {

View File

@ -45,6 +45,7 @@ import org.hibernate.sql.exec.spi.JdbcSelect;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.basic.BasicResult;
import org.hibernate.sql.results.internal.SqlSelectionImpl;
import org.hibernate.sql.results.spi.ListResultsConsumer;
import org.jboss.logging.Logger;
@ -276,7 +277,7 @@ public class MatchingIdSelectionHelper {
jdbcParameterBindings,
SqlOmittingQueryOptions.omitSqlQueryOptions( executionContext, idSelectJdbcOperation ),
row -> row,
true
ListResultsConsumer.UniqueSemantic.FILTER
);
}
}

View File

@ -58,6 +58,7 @@ import org.hibernate.sql.exec.spi.JdbcSelect;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.basic.BasicResult;
import org.hibernate.sql.results.internal.SqlSelectionImpl;
import org.hibernate.sql.results.spi.ListResultsConsumer;
import org.hibernate.type.spi.TypeConfiguration;
/**
@ -207,7 +208,7 @@ public abstract class AbstractCteMutationHandler extends AbstractMutationHandler
jdbcParameterBindings,
SqlOmittingQueryOptions.omitSqlQueryOptions( executionContext, select ),
row -> row[0],
false
ListResultsConsumer.UniqueSemantic.NONE
);
return ( (Number) list.get( 0 ) ).intValue();
}

View File

@ -69,7 +69,7 @@ public class JdbcSelectExecutorStandardImpl implements JdbcSelectExecutor {
JdbcParameterBindings jdbcParameterBindings,
ExecutionContext executionContext,
RowTransformer<R> rowTransformer,
boolean uniqueFilter) {
ListResultsConsumer.UniqueSemantic uniqueSemantic) {
// Only do auto flushing for top level queries
return executeQuery(
jdbcSelect,
@ -80,29 +80,7 @@ public class JdbcSelectExecutorStandardImpl implements JdbcSelectExecutor {
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( sql ),
ListResultsConsumer.instance( uniqueFilter, false )
);
}
@Override
public <R> List<R> list(
JdbcSelect jdbcSelect,
JdbcParameterBindings jdbcParameterBindings,
ExecutionContext executionContext,
RowTransformer<R> rowTransformer,
boolean uniqueFilter,
boolean singleResultExpected) {
// Only do auto flushing for top level queries
return executeQuery(
jdbcSelect,
jdbcParameterBindings,
executionContext,
rowTransformer,
(sql) -> executionContext.getSession()
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( sql ),
ListResultsConsumer.instance( uniqueFilter, singleResultExpected )
ListResultsConsumer.instance( uniqueSemantic )
);
}

View File

@ -12,6 +12,7 @@ import java.util.stream.Stream;
import org.hibernate.Incubating;
import org.hibernate.ScrollMode;
import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.sql.results.spi.ListResultsConsumer;
import org.hibernate.sql.results.spi.RowTransformer;
/**
@ -23,20 +24,12 @@ import org.hibernate.sql.results.spi.RowTransformer;
public interface JdbcSelectExecutor {
// todo (6.0) : Ideally we'd have a singular place (JdbcServices? ServiceRegistry?) to obtain these executors
<R> List<R> list(
JdbcSelect jdbcSelect,
JdbcParameterBindings jdbcParameterBindings,
ExecutionContext executionContext,
RowTransformer<R> rowTransformer,
boolean uniqueFilter);
<R> List<R> list(
JdbcSelect jdbcSelect,
JdbcParameterBindings jdbcParameterBindings,
ExecutionContext executionContext,
RowTransformer<R> rowTransformer,
boolean uniqueFilter,
boolean onlyOne);
ListResultsConsumer.UniqueSemantic uniqueSemantic);
<R> ScrollableResultsImplementor<R> scroll(
JdbcSelect jdbcSelect,

View File

@ -30,12 +30,15 @@ public class ListResultsConsumer<R> implements ResultsConsumer<List<R>, R> {
private static final ListResultsConsumer NORMAL_INSTANCE = new ListResultsConsumer( UniqueSemantic.NONE );
private static final ListResultsConsumer UNIQUE_INSTANCE = new ListResultsConsumer( UniqueSemantic.ASSERT );
@SuppressWarnings("unchecked")
public static <R> ListResultsConsumer<R> instance(boolean uniqueFilter, boolean singleResultExpected) {
if ( singleResultExpected ) {
return UNIQUE_INSTANCE;
public static <R> ListResultsConsumer<R> instance(UniqueSemantic uniqueSemantic) {
switch ( uniqueSemantic ) {
case ASSERT:
return UNIQUE_INSTANCE;
case FILTER:
return UNIQUE_FILTER_INSTANCE;
default:
return NORMAL_INSTANCE;
}
return uniqueFilter ? UNIQUE_FILTER_INSTANCE : NORMAL_INSTANCE;
}
public enum UniqueSemantic {
@ -64,14 +67,9 @@ public class ListResultsConsumer<R> implements ResultsConsumer<List<R>, R> {
final List<R> results = new ArrayList<>();
if ( uniqueSemantic == UniqueSemantic.NONE ) {
while ( rowProcessingState.next() ) {
results.add( rowReader.readRow( rowProcessingState, processingOptions ) );
rowProcessingState.finishRowProcessing();
}
}
else {
boolean uniqueRows = false;
boolean uniqueRows = false;
if ( uniqueSemantic != UniqueSemantic.NONE ) {
final Class<R> resultJavaType = rowReader.getResultJavaType();
if ( resultJavaType != null && !resultJavaType.isArray() ) {
final EntityPersister entityDescriptor = session.getFactory().getMetamodel().findEntityDescriptor(
@ -80,29 +78,28 @@ public class ListResultsConsumer<R> implements ResultsConsumer<List<R>, R> {
uniqueRows = true;
}
}
}
if ( uniqueRows ) {
final List<JavaTypeDescriptor> resultJavaTypeDescriptors = rowReader.getResultJavaTypeDescriptors();
assert resultJavaTypeDescriptors.size() == 1;
final JavaTypeDescriptor<R> resultJavaTypeDescriptor = resultJavaTypeDescriptors.get( 0 );
while ( rowProcessingState.next() ) {
final R row = rowReader.readRow( rowProcessingState, processingOptions );
boolean add = true;
if ( uniqueRows ) {
assert resultJavaTypeDescriptors.size() == 1;
for ( R existingRow : results ) {
if ( resultJavaTypeDescriptor.areEqual( existingRow, row ) ) {
if ( uniqueSemantic == UniqueSemantic.ASSERT && !rowProcessingState.hasCollectionInitializers() ) {
throw new HibernateException(
"More than one row with the given identifier was found: " +
jdbcValuesSourceProcessingState.getExecutionContext()
.getEntityId() +
", for class: " +
resultJavaType.getName()
);
}
add = false;
break;
for ( R existingRow : results ) {
if ( resultJavaTypeDescriptor.areEqual( existingRow, row ) ) {
if ( uniqueSemantic == UniqueSemantic.ASSERT && !rowProcessingState.hasCollectionInitializers() ) {
throw new HibernateException(
"More than one row with the given identifier was found: " +
jdbcValuesSourceProcessingState.getExecutionContext()
.getEntityId() +
", for class: " +
rowReader.getResultJavaType().getName()
);
}
add = false;
break;
}
}
if ( add ) {
@ -111,6 +108,12 @@ public class ListResultsConsumer<R> implements ResultsConsumer<List<R>, R> {
rowProcessingState.finishRowProcessing();
}
}
else {
while ( rowProcessingState.next() ) {
results.add( rowReader.readRow( rowProcessingState, processingOptions ) );
rowProcessingState.finishRowProcessing();
}
}
persistenceContext.initializeNonLazyCollections();
jdbcValuesSourceProcessingState.finishUp();
return results;