HHH-18170 Subquery randomly generating wrong SQL due to duplicate alias

This commit is contained in:
Marco Pelagatti 2024-05-27 18:18:55 +02:00 committed by Christian Beikov
parent 1919409ffc
commit 3790c19ccc
4 changed files with 19 additions and 8 deletions

View File

@ -11,6 +11,8 @@ import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmPath;
import java.util.concurrent.atomic.AtomicLong;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@ -27,6 +29,8 @@ public class SqmCreationHelper {
*/ */
public static final String IMPLICIT_ALIAS = "{implicit}"; public static final String IMPLICIT_ALIAS = "{implicit}";
private static final AtomicLong UNIQUE_ID_COUNTER = new AtomicLong();
public static NavigablePath buildRootNavigablePath(String base, String alias) { public static NavigablePath buildRootNavigablePath(String base, String alias) {
return new NavigablePath( base, determineAlias( alias ) ); return new NavigablePath( base, determineAlias( alias ) );
} }
@ -35,10 +39,14 @@ public class SqmCreationHelper {
return lhs.append( base, determineAlias( alias ) ); return lhs.append( base, determineAlias( alias ) );
} }
public static String acquireUniqueAlias() {
return Long.toString(UNIQUE_ID_COUNTER.incrementAndGet());
}
public static String determineAlias(String alias) { public static String determineAlias(String alias) {
// Make sure we always create a unique alias, otherwise we might use a wrong table group for the same join // Make sure we always create a unique alias, otherwise we might use a wrong table group for the same join
if ( alias == null ) { if ( alias == null ) {
return Long.toString( System.nanoTime() ); return acquireUniqueAlias();
} }
else if ( alias == IMPLICIT_ALIAS ) { else if ( alias == IMPLICIT_ALIAS ) {
return null; return null;

View File

@ -15,6 +15,7 @@ import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.internal.BasicAttributeMapping; import org.hibernate.metamodel.mapping.internal.BasicAttributeMapping;
import org.hibernate.query.sqm.spi.SqmCreationHelper;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.ast.SqlAstWalker; import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.spi.SqlAstCreationState; import org.hibernate.sql.ast.spi.SqlAstCreationState;
@ -46,7 +47,7 @@ public class EmbeddableValuedExpression<T> implements Expression, DomainResultPr
assert mapping != null; assert mapping != null;
assert sqlExpression != null; assert sqlExpression != null;
assert mapping.getEmbeddableTypeDescriptor().getNumberOfAttributeMappings() == sqlExpression.getExpressions().size(); assert mapping.getEmbeddableTypeDescriptor().getNumberOfAttributeMappings() == sqlExpression.getExpressions().size();
this.navigablePath = baseNavigablePath.append( mapping.getPartName(), Long.toString( System.nanoTime() ) ); this.navigablePath = baseNavigablePath.append( mapping.getPartName(), SqmCreationHelper.acquireUniqueAlias());
this.mapping = mapping; this.mapping = mapping;
this.sqlExpression = sqlExpression; this.sqlExpression = sqlExpression;
} }

View File

@ -16,6 +16,7 @@ import org.hibernate.query.criteria.JpaCteCriteria;
import org.hibernate.query.criteria.JpaRoot; import org.hibernate.query.criteria.JpaRoot;
import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SqmQuerySource; import org.hibernate.query.sqm.SqmQuerySource;
import org.hibernate.query.sqm.spi.SqmCreationHelper;
import org.hibernate.query.sqm.tree.cte.SqmCteStatement; import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
import org.hibernate.query.sqm.tree.expression.SqmParameter; import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.query.sqm.tree.from.SqmRoot; import org.hibernate.query.sqm.tree.from.SqmRoot;
@ -84,21 +85,21 @@ public abstract class AbstractSqmDmlStatement<E>
@Override @Override
public <X> JpaCteCriteria<X> with(AbstractQuery<X> criteria) { public <X> JpaCteCriteria<X> with(AbstractQuery<X> criteria) {
return withInternal( Long.toString( System.nanoTime() ), criteria ); return withInternal( SqmCreationHelper.acquireUniqueAlias(), criteria );
} }
@Override @Override
public <X> JpaCteCriteria<X> withRecursiveUnionAll( public <X> JpaCteCriteria<X> withRecursiveUnionAll(
AbstractQuery<X> baseCriteria, AbstractQuery<X> baseCriteria,
Function<JpaCteCriteria<X>, AbstractQuery<X>> recursiveCriteriaProducer) { Function<JpaCteCriteria<X>, AbstractQuery<X>> recursiveCriteriaProducer) {
return withInternal( Long.toString( System.nanoTime() ), baseCriteria, false, recursiveCriteriaProducer ); return withInternal( SqmCreationHelper.acquireUniqueAlias(), baseCriteria, false, recursiveCriteriaProducer );
} }
@Override @Override
public <X> JpaCteCriteria<X> withRecursiveUnionDistinct( public <X> JpaCteCriteria<X> withRecursiveUnionDistinct(
AbstractQuery<X> baseCriteria, AbstractQuery<X> baseCriteria,
Function<JpaCteCriteria<X>, AbstractQuery<X>> recursiveCriteriaProducer) { Function<JpaCteCriteria<X>, AbstractQuery<X>> recursiveCriteriaProducer) {
return withInternal( Long.toString( System.nanoTime() ), baseCriteria, true, recursiveCriteriaProducer ); return withInternal( SqmCreationHelper.acquireUniqueAlias(), baseCriteria, true, recursiveCriteriaProducer );
} }
@Override @Override

View File

@ -19,6 +19,7 @@ import org.hibernate.query.criteria.JpaCteCriteria;
import org.hibernate.query.criteria.JpaRoot; import org.hibernate.query.criteria.JpaRoot;
import org.hibernate.query.criteria.JpaSelection; import org.hibernate.query.criteria.JpaSelection;
import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.spi.SqmCreationHelper;
import org.hibernate.query.sqm.tree.AbstractSqmNode; import org.hibernate.query.sqm.tree.AbstractSqmNode;
import org.hibernate.query.sqm.tree.SqmCopyContext; import org.hibernate.query.sqm.tree.SqmCopyContext;
import org.hibernate.query.sqm.tree.cte.SqmCteStatement; import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
@ -112,21 +113,21 @@ public abstract class AbstractSqmSelectQuery<T>
@Override @Override
public <X> JpaCteCriteria<X> with(AbstractQuery<X> criteria) { public <X> JpaCteCriteria<X> with(AbstractQuery<X> criteria) {
return withInternal( Long.toString( System.nanoTime() ), criteria ); return withInternal( SqmCreationHelper.acquireUniqueAlias(), criteria );
} }
@Override @Override
public <X> JpaCteCriteria<X> withRecursiveUnionAll( public <X> JpaCteCriteria<X> withRecursiveUnionAll(
AbstractQuery<X> baseCriteria, AbstractQuery<X> baseCriteria,
Function<JpaCteCriteria<X>, AbstractQuery<X>> recursiveCriteriaProducer) { Function<JpaCteCriteria<X>, AbstractQuery<X>> recursiveCriteriaProducer) {
return withInternal( Long.toString( System.nanoTime() ), baseCriteria, false, recursiveCriteriaProducer ); return withInternal( SqmCreationHelper.acquireUniqueAlias(), baseCriteria, false, recursiveCriteriaProducer );
} }
@Override @Override
public <X> JpaCteCriteria<X> withRecursiveUnionDistinct( public <X> JpaCteCriteria<X> withRecursiveUnionDistinct(
AbstractQuery<X> baseCriteria, AbstractQuery<X> baseCriteria,
Function<JpaCteCriteria<X>, AbstractQuery<X>> recursiveCriteriaProducer) { Function<JpaCteCriteria<X>, AbstractQuery<X>> recursiveCriteriaProducer) {
return withInternal( Long.toString( System.nanoTime() ), baseCriteria, true, recursiveCriteriaProducer ); return withInternal( SqmCreationHelper.acquireUniqueAlias(), baseCriteria, true, recursiveCriteriaProducer );
} }
@Override @Override