From da2ee40aef48d8cd2e99056bee71e441975dc1f2 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Fri, 27 Jun 2025 12:26:22 +0200 Subject: [PATCH 1/2] minor cleanups to SqmQueryGroup --- .../query/sqm/tree/select/SqmQueryGroup.java | 88 ++++++++++--------- 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmQueryGroup.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmQueryGroup.java index 3186d0f6b963..b3a73133d3c7 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmQueryGroup.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmQueryGroup.java @@ -5,12 +5,11 @@ package org.hibernate.query.sqm.tree.select; import java.util.ArrayList; -import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Objects; -import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.AssertionFailure; import org.hibernate.query.common.FetchClauseType; import org.hibernate.query.SemanticException; import org.hibernate.query.sqm.SetOperator; @@ -27,6 +26,9 @@ import org.hibernate.query.sqm.tree.from.SqmJoin; import org.hibernate.type.descriptor.java.JavaType; +import static java.util.Collections.unmodifiableList; +import static org.hibernate.internal.util.collections.CollectionHelper.listOf; + /** * A grouped list of queries connected through a certain set operator. * @@ -38,7 +40,7 @@ public class SqmQueryGroup extends SqmQueryPart implements JpaQueryGroup queryPart) { - this( queryPart.nodeBuilder(), null, CollectionHelper.listOf( queryPart ) ); + this( queryPart.nodeBuilder(), null, listOf( queryPart ) ); } public SqmQueryGroup( @@ -56,20 +58,17 @@ public SqmQueryPart copy(SqmCopyContext context) { if ( existing != null ) { return existing; } - final List> queryParts = new ArrayList<>( this.queryParts.size() ); - for ( SqmQueryPart queryPart : this.queryParts ) { - queryParts.add( queryPart.copy( context ) ); + else { + final List> queryParts = new ArrayList<>( this.queryParts.size() ); + for ( SqmQueryPart queryPart : this.queryParts ) { + queryParts.add( queryPart.copy( context ) ); + } + final SqmQueryGroup queryGroup = + context.registerCopy( this, + new SqmQueryGroup<>( nodeBuilder(), setOperator, queryParts ) ); + copyTo( queryGroup, context ); + return queryGroup; } - final SqmQueryGroup queryGroup = context.registerCopy( - this, - new SqmQueryGroup<>( - nodeBuilder(), - setOperator, - queryParts - ) - ); - copyTo( queryGroup, context ); - return queryGroup; } public List> queryParts() { @@ -88,7 +87,9 @@ public SqmQuerySpec getLastQuerySpec() { @Override public boolean isSimpleQueryPart() { - return setOperator == null && queryParts.size() == 1 && queryParts.get( 0 ).isSimpleQueryPart(); + return setOperator == null + && queryParts.size() == 1 + && queryParts.get( 0 ).isSimpleQueryPart(); } @Override @@ -98,7 +99,7 @@ public X accept(SemanticQueryWalker walker) { @Override public List> getQueryParts() { - return Collections.unmodifiableList( queryParts ); + return unmodifiableList( queryParts ); } public SetOperator getSetOperator() { @@ -156,12 +157,11 @@ private void validateQueryGroupFetchStructure(List> ty final int firstSelectionSize = typedNodes.size(); for ( int i = 0; i < queryParts.size(); i++ ) { final SqmQueryPart queryPart = queryParts.get( i ); - if ( queryPart instanceof SqmQueryGroup ) { - ( (SqmQueryGroup) queryPart ).validateQueryGroupFetchStructure( typedNodes ); + if ( queryPart instanceof SqmQueryGroup queryGroup ) { + queryGroup.validateQueryGroupFetchStructure( typedNodes ); } - else { - final SqmQuerySpec querySpec = (SqmQuerySpec) queryPart; - final List> selections = querySpec.getSelectClause().getSelections(); + else if ( queryPart instanceof SqmQuerySpec querySpec ) { + final var selections = querySpec.getSelectClause().getSelections(); if ( firstSelectionSize != selections.size() ) { throw new SemanticException( "All query parts in a query group must have the same arity" ); } @@ -175,31 +175,25 @@ private void validateQueryGroupFetchStructure(List> ty ); } if ( firstSqmSelection instanceof SqmFrom firstFrom ) { - final SqmFrom from = (SqmFrom) selections.get( j ).getSelectableNode(); + final var from = (SqmFrom) selections.get( j ).getSelectableNode(); validateFetchesMatch( firstFrom, from ); } } } + else { + throw new AssertionFailure( "Unrecognized SqmQueryPart subtype" ); + } } } private void validateFetchesMatch(SqmFrom firstFrom, SqmFrom from) { - final Iterator> firstJoinIter = firstFrom.getSqmJoins().iterator(); - final Iterator> joinIter = from.getSqmJoins().iterator(); + final var firstJoinIter = firstFrom.getSqmJoins().iterator(); + final var joinIter = from.getSqmJoins().iterator(); while ( firstJoinIter.hasNext() ) { final SqmJoin firstSqmJoin = firstJoinIter.next(); if ( firstSqmJoin instanceof SqmAttributeJoin firstAttrJoin ) { if ( firstAttrJoin.isFetched() ) { - SqmAttributeJoin matchingAttrJoin = null; - while ( joinIter.hasNext() ) { - final SqmJoin sqmJoin = joinIter.next(); - if ( sqmJoin instanceof SqmAttributeJoin attrJoin ) { - if ( attrJoin.isFetched() ) { - matchingAttrJoin = attrJoin; - break; - } - } - } + final var matchingAttrJoin = findFirstFetchJoin( joinIter ); if ( matchingAttrJoin == null || firstAttrJoin.getModel() != matchingAttrJoin.getModel() ) { throw new SemanticException( "All query parts in a query group must have the same join fetches in the same order" @@ -211,15 +205,23 @@ private void validateFetchesMatch(SqmFrom firstFrom, SqmFrom from) { } // At this point, the other iterator should only contain non-fetch joins while ( joinIter.hasNext() ) { - final SqmJoin sqmJoin = joinIter.next(); - if ( sqmJoin instanceof SqmAttributeJoin attrJoin ) { - if ( attrJoin.isFetched() ) { - throw new SemanticException( - "All query parts in a query group must have the same join fetches in the same order" - ); - } + if ( joinIter.next() instanceof SqmAttributeJoin attrJoin + && attrJoin.isFetched() ) { + throw new SemanticException( + "All query parts in a query group must have the same join fetches in the same order" + ); + } + } + } + + private static SqmAttributeJoin findFirstFetchJoin(Iterator> joinIter) { + while ( joinIter.hasNext() ) { + if ( joinIter.next() instanceof SqmAttributeJoin attrJoin + && attrJoin.isFetched() ) { + return attrJoin; } } + return null; } @Override From 7cd5aa8fdaf644e118949cf3a75e9733db86945e Mon Sep 17 00:00:00 2001 From: Gavin King Date: Fri, 27 Jun 2025 12:26:54 +0200 Subject: [PATCH 2/2] squash IntelliJ grammar nags --- hibernate-core/src/main/java/org/hibernate/sql/Template.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/sql/Template.java b/hibernate-core/src/main/java/org/hibernate/sql/Template.java index d834ef26d1b2..9e16aba66f8b 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/Template.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/Template.java @@ -145,13 +145,13 @@ public static String renderWhereStringTemplate( // IMPL NOTE: The basic process here is to tokenize the incoming string and to iterate over each token // in turn. As we process each token, we set a series of flags used to indicate the type of context in - // which the tokens occur. Depending on the state of those flags we decide whether we need to qualify + // which the tokens occur. Depending on the state of those flags, we decide whether we need to qualify // identifier references. // WARNING TO MAINTAINERS: This is a simple scanner-based state machine. Please don't attempt to turn it into // a parser for SQL, no matter how "special" your case is. What I mean by this is: don't write code which // attempts to recognize the grammar of SQL, not even little bits of SQL. Previous "enhancements" to this - // function did not respect this concept, and resulted in code which was fragile and unmaintainable. If + // function did not respect this concept and resulted in code which was fragile and unmaintainable. If // lookahead is truly necessary, use the lookahead() function provided below. final String symbols = PUNCTUATION + WHITESPACE + dialect.openQuote() + dialect.closeQuote();