HHH-16051 Avoid stateful lambdas on invocations of Stack#findCurrentFirst
This commit is contained in:
parent
c570b11dcd
commit
84a652bfe7
|
@ -147,7 +147,11 @@ public class OracleSqlAstTranslator<T extends JdbcOperation> extends AbstractSql
|
|||
}
|
||||
|
||||
private boolean isPartOfQueryGroup() {
|
||||
return getQueryPartStack().findCurrentFirst( part -> part instanceof QueryGroup ? part : null ) != null;
|
||||
return getQueryPartStack().findCurrentFirst( OracleSqlAstTranslator::partIsQueryGroup ) != null;
|
||||
}
|
||||
|
||||
private static QueryPart partIsQueryGroup(final QueryPart part) {
|
||||
return part instanceof QueryGroup ? part : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -6,9 +6,12 @@
|
|||
*/
|
||||
package org.hibernate.internal.util.collections;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
|
||||
/**
|
||||
* Stack implementation exposing useful methods for Hibernate needs.
|
||||
*
|
||||
|
@ -62,4 +65,21 @@ public interface Stack<T> {
|
|||
* returned from `action` stops the iteration and is returned from here
|
||||
*/
|
||||
<X> X findCurrentFirst(Function<T, X> action);
|
||||
|
||||
/**
|
||||
* Runs a function on each couple defined as {Y,T} in which Y
|
||||
* is fixed, and T is each instance of this stack.
|
||||
* Not all Ts might be presented as the iteration is interrupted as
|
||||
* soon as the first non-null value is returned by the (bi)function,
|
||||
* which is then returned from this function.
|
||||
* @param parameter a parameter to be passed to the (bi)funtion
|
||||
* @param biFunction a (bi)function taking as input parameter Y and each of the T
|
||||
* from the current stack, and return type of X.
|
||||
* @return the first non-null result by the function, or null if no matches.
|
||||
* @param <X> the return type of the function
|
||||
* @param <Y> the type of the fixed parameter
|
||||
*/
|
||||
@Incubating
|
||||
<X,Y> X findCurrentFirstWithParameter(Y parameter, BiFunction<T, Y, X> biFunction);
|
||||
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.internal.util.collections;
|
|||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
|
@ -126,4 +127,18 @@ public final class StandardStack<T> implements Stack<T> {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X,Y> X findCurrentFirstWithParameter(Y parameter, BiFunction<T, Y, X> biFunction) {
|
||||
if ( internalStack == null ) {
|
||||
return null;
|
||||
}
|
||||
for ( T t : internalStack ) {
|
||||
final X result = biFunction.apply( t, parameter );
|
||||
if ( result != null ) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import org.hibernate.metamodel.model.domain.EntityDomainType;
|
|||
import org.hibernate.query.criteria.JpaCteCriteria;
|
||||
import org.hibernate.query.criteria.JpaCteCriteriaAttribute;
|
||||
import org.hibernate.query.criteria.JpaSearchOrder;
|
||||
import org.hibernate.query.sqm.tree.SqmQuery;
|
||||
import org.hibernate.query.sqm.tree.cte.SqmCteTableColumn;
|
||||
import org.hibernate.query.sqm.tree.cte.SqmSearchClauseSpecification;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmCteRoot;
|
||||
|
@ -339,17 +340,18 @@ public class QuerySplitter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmCteStatement<?> findCteStatement(String name) {
|
||||
return processingStateStack.findCurrentFirst(
|
||||
state -> {
|
||||
if ( state.getProcessingQuery() instanceof SqmCteContainer ) {
|
||||
final SqmCteContainer container = (SqmCteContainer) state.getProcessingQuery();
|
||||
return container.getCteStatement( name );
|
||||
public SqmCteStatement<?> findCteStatement(final String name) {
|
||||
return processingStateStack.findCurrentFirstWithParameter( name, UnmappedPolymorphismReplacer::matchCteStatement );
|
||||
}
|
||||
|
||||
private static SqmCteStatement<?> matchCteStatement(final SqmCreationProcessingState state, final String cteName) {
|
||||
final SqmQuery<?> processingQuery = state.getProcessingQuery();
|
||||
if ( processingQuery instanceof SqmCteContainer ) {
|
||||
final SqmCteContainer container = (SqmCteContainer) processingQuery;
|
||||
return container.getCteStatement( cteName );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmDeleteStatement<R> visitDeleteStatement(SqmDeleteStatement<?> statement) {
|
||||
|
|
|
@ -1944,16 +1944,16 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
if ( currentPotentialRecursiveCte != null && name.equals( currentPotentialRecursiveCte.getName() ) ) {
|
||||
return (SqmCteStatement<?>) currentPotentialRecursiveCte;
|
||||
}
|
||||
return processingStateStack.findCurrentFirst(
|
||||
state -> {
|
||||
return processingStateStack.findCurrentFirstWithParameter( name, SemanticQueryBuilder::matchCteStatement );
|
||||
}
|
||||
|
||||
private static SqmCteStatement<?> matchCteStatement(SqmCreationProcessingState state, String n) {
|
||||
if ( state.getProcessingQuery() instanceof SqmCteContainer ) {
|
||||
final SqmCteContainer container = (SqmCteContainer) state.getProcessingQuery();
|
||||
return container.getCteStatement( name );
|
||||
return container.getCteStatement( n );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmRoot<?> visitRootSubquery(HqlParser.RootSubqueryContext ctx) {
|
||||
|
|
|
@ -573,6 +573,31 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
.getJpaCriteriaParamResolutions();
|
||||
}
|
||||
|
||||
private static Boolean stackMatchHelper(SqlAstProcessingState processingState, SqlAstProcessingState c) {
|
||||
if ( !( processingState instanceof SqlAstQueryPartProcessingState ) ) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
if ( processingState == c ) {
|
||||
return null;
|
||||
}
|
||||
final QueryPart part = ( (SqlAstQueryPartProcessingState) processingState ).getInflightQueryPart();
|
||||
if ( part instanceof QueryGroup ) {
|
||||
if ( ( (QueryGroup) part ).getQueryParts().isEmpty() ) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
private static Boolean matchSqlAstWithQueryPart(SqlAstProcessingState state, QueryPart cteQueryPartLocal) {
|
||||
if ( state instanceof SqlAstQueryPartProcessingState ) {
|
||||
if ( ( (SqlAstQueryPartProcessingState) state ).getInflightQueryPart() == cteQueryPartLocal ) {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Map<SqmParameter<?>, MappingModelExpressible<?>> getSqmParameterMappingModelExpressibleResolutions() {
|
||||
return sqmParameterMappingModelTypes;
|
||||
}
|
||||
|
@ -2226,23 +2251,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
// Since we only want to create domain results for the first/left-most query spec within query groups,
|
||||
// we have to check if the current query spec is the left-most.
|
||||
// This is the case when all upper level in-flight query groups are still empty
|
||||
collectDomainResults = needsDomainResults && processingStateStack.findCurrentFirst(
|
||||
processingState -> {
|
||||
if ( !( processingState instanceof SqlAstQueryPartProcessingState ) ) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
if ( processingState == current ) {
|
||||
return null;
|
||||
}
|
||||
final QueryPart part = ( (SqlAstQueryPartProcessingState) processingState ).getInflightQueryPart();
|
||||
if ( part instanceof QueryGroup ) {
|
||||
if ( ( (QueryGroup) part ).getQueryParts().isEmpty() ) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
) == null;
|
||||
collectDomainResults = needsDomainResults && processingStateStack.findCurrentFirstWithParameter( current, BaseSqmToSqlAstConverter::stackMatchHelper ) == null;
|
||||
}
|
||||
// this `currentSqlSelectionCollector().next()` is meant solely for resolving
|
||||
// literal reference to a selection-item in the order-by or group-by clause.
|
||||
|
@ -2825,16 +2834,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
}
|
||||
final QueryPart cteQueryPart = ( (SelectStatement) cteStatement.getCteDefinition() ).getQueryPart();
|
||||
// If the query part of the CTE is one which we are currently processing, then this is a recursive CTE
|
||||
if ( cteQueryPart instanceof QueryGroup && Boolean.TRUE == processingStateStack.findCurrentFirst(
|
||||
state -> {
|
||||
if ( state instanceof SqlAstQueryPartProcessingState ) {
|
||||
if ( ( (SqlAstQueryPartProcessingState) state ).getInflightQueryPart() == cteQueryPart ) {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
) ) {
|
||||
if ( cteQueryPart instanceof QueryGroup && Boolean.TRUE == processingStateStack.findCurrentFirstWithParameter( cteQueryPart, BaseSqmToSqlAstConverter::matchSqlAstWithQueryPart ) ) {
|
||||
cteStatement.setRecursive();
|
||||
}
|
||||
final AnonymousTupleTableGroupProducer tableGroupProducer = cteStatement.getCteTable().getTableGroupProducer();
|
||||
|
|
|
@ -310,6 +310,13 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
private JdbcParameter limitParameter;
|
||||
private ForUpdateClause forUpdate;
|
||||
|
||||
private static Clause matchWithClause(Clause clause) {
|
||||
if ( clause == Clause.WITH ) {
|
||||
return Clause.WITH;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Dialect getDialect() {
|
||||
return dialect;
|
||||
}
|
||||
|
@ -470,15 +477,15 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
}
|
||||
|
||||
public MutationStatement getCurrentDmlStatement() {
|
||||
return statementStack.findCurrentFirst(
|
||||
stmt -> {
|
||||
return statementStack.findCurrentFirst( AbstractSqlAstTranslator::matchMutationStatementNoInsertSelect );
|
||||
}
|
||||
|
||||
private static MutationStatement matchMutationStatementNoInsertSelect(Statement stmt) {
|
||||
if ( stmt instanceof MutationStatement && !( stmt instanceof InsertSelectStatement ) ) {
|
||||
return (MutationStatement) stmt;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
protected SqlAstNodeRenderingMode getParameterRenderingMode() {
|
||||
return parameterRenderingMode;
|
||||
|
@ -688,16 +695,17 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
}
|
||||
|
||||
protected boolean inOverOrWithinGroupClause() {
|
||||
return clauseStack.findCurrentFirst(
|
||||
clause -> {
|
||||
return clauseStack.findCurrentFirst( AbstractSqlAstTranslator::matchOverOrWithinGroupClauses ) != null;
|
||||
}
|
||||
|
||||
private static Boolean matchOverOrWithinGroupClauses(final Clause clause) {
|
||||
switch ( clause ) {
|
||||
case OVER:
|
||||
case WITHIN_GROUP:
|
||||
return true;
|
||||
}
|
||||
return Boolean.TRUE;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
) != null;
|
||||
}
|
||||
|
||||
protected Stack<Clause> getClauseStack() {
|
||||
|
@ -722,15 +730,26 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
return currentCteStatement;
|
||||
}
|
||||
|
||||
protected CteStatement getCteStatement(String cteName) {
|
||||
return statementStack.findCurrentFirst(
|
||||
stmt -> {
|
||||
protected CteStatement getCteStatement(final String cteName) {
|
||||
return statementStack.findCurrentFirstWithParameter( cteName, AbstractSqlAstTranslator::matchCteStatement );
|
||||
}
|
||||
|
||||
private static CteStatement matchCteStatement(final Statement stmt, final String cteName) {
|
||||
if ( stmt instanceof CteContainer ) {
|
||||
return ( (CteContainer) stmt ).getCteStatement( cteName );
|
||||
final CteContainer cteContainer = (CteContainer) stmt;
|
||||
return cteContainer.getCteStatement( cteName );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
);
|
||||
|
||||
private static CteContainer matchCteContainerByStatement(final Statement stmt, final String cteName) {
|
||||
if ( stmt instanceof CteContainer ) {
|
||||
final CteContainer cteContainer = (CteContainer) stmt;
|
||||
if ( cteContainer.getCteStatement( cteName ) != null ) {
|
||||
return cteContainer;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1508,14 +1527,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
pushToTopLevel = !supportsNestedWithClause()
|
||||
|| !supportsWithClauseInSubquery() && isInSubquery();
|
||||
}
|
||||
final boolean inNestedWithClause = clauseStack.findCurrentFirst(
|
||||
clause -> {
|
||||
if ( clause == Clause.WITH ) {
|
||||
return Clause.WITH;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
) != null;
|
||||
final boolean inNestedWithClause = clauseStack.findCurrentFirst( AbstractSqlAstTranslator::matchWithClause ) != null;
|
||||
clauseStack.push( Clause.WITH );
|
||||
if ( !pushToTopLevel ) {
|
||||
appendSql( "with " );
|
||||
|
@ -1796,17 +1808,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
}
|
||||
if ( !supportsWithClauseInSubquery() && isInSubquery() ) {
|
||||
final String cteName = tableGroup.getPrimaryTableReference().getTableId();
|
||||
final CteContainer cteOwner = statementStack.findCurrentFirst(
|
||||
stmt -> {
|
||||
if ( stmt instanceof CteContainer ) {
|
||||
final CteContainer cteContainer = (CteContainer) stmt;
|
||||
if ( cteContainer.getCteStatement( cteName ) != null ) {
|
||||
return cteContainer;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
);
|
||||
final CteContainer cteOwner = statementStack.findCurrentFirstWithParameter( cteName, AbstractSqlAstTranslator::matchCteContainerByStatement );
|
||||
// If the CTE is owned by the root statement, it will be rendered as CTE, so we can refer to it
|
||||
return cteOwner != statementStack.getRoot() && !cteOwner.getCteStatement( cteName ).isRecursive();
|
||||
}
|
||||
|
|
|
@ -48,22 +48,16 @@ public class LoadContexts {
|
|||
}
|
||||
}
|
||||
|
||||
public LoadingEntityEntry findLoadingEntityEntry(EntityKey entityKey) {
|
||||
return jdbcValuesSourceProcessingStateStack.findCurrentFirst(
|
||||
state -> state.findLoadingEntityLocally( entityKey )
|
||||
);
|
||||
public LoadingEntityEntry findLoadingEntityEntry(final EntityKey entityKey) {
|
||||
return jdbcValuesSourceProcessingStateStack.findCurrentFirstWithParameter( entityKey, JdbcValuesSourceProcessingState::findLoadingEntityLocally );
|
||||
}
|
||||
|
||||
public LoadingCollectionEntry findLoadingCollectionEntry(CollectionKey collectionKey) {
|
||||
return jdbcValuesSourceProcessingStateStack.findCurrentFirst(
|
||||
state -> state.findLoadingCollectionLocally( collectionKey )
|
||||
);
|
||||
public LoadingCollectionEntry findLoadingCollectionEntry(final CollectionKey collectionKey) {
|
||||
return jdbcValuesSourceProcessingStateStack.findCurrentFirstWithParameter( collectionKey, JdbcValuesSourceProcessingState::findLoadingCollectionLocally );
|
||||
}
|
||||
|
||||
public Initializer findInitializer(EntityUniqueKey key){
|
||||
return jdbcValuesSourceProcessingStateStack.findCurrentFirst(
|
||||
state -> state.findInitializer( key )
|
||||
);
|
||||
public Initializer findInitializer(final EntityUniqueKey key){
|
||||
return jdbcValuesSourceProcessingStateStack.findCurrentFirstWithParameter( key, JdbcValuesSourceProcessingState::findInitializer );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,11 +69,6 @@ public class LoadContexts {
|
|||
return persistenceContext;
|
||||
}
|
||||
|
||||
private SharedSessionContractImplementor getSession() {
|
||||
return getPersistenceContext().getSession();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Release internal state associated with *all* result sets.
|
||||
* <p>
|
||||
|
|
Loading…
Reference in New Issue