Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,15 @@ public class SqmPathRegistryImpl implements SqmPathRegistry {

public SqmPathRegistryImpl(SqmCreationProcessingState associatedProcessingState) {
this.associatedProcessingState = associatedProcessingState;
this.jpaCompliance = associatedProcessingState.getCreationState().getCreationContext().getNodeBuilder().getJpaCompliance();
this.jpaCompliance =
associatedProcessingState.getCreationState().getCreationContext()
.getNodeBuilder().getJpaCompliance();
}

private String handleAliasCaseSensitivity(String alias) {
return jpaCompliance.isJpaQueryComplianceEnabled()
? alias.toLowerCase( Locale.getDefault() )
: alias;
}

@Override
Expand All @@ -63,35 +71,33 @@ public void register(SqmPath<?> sqmPath) {
// Regarding part #1 (add to the path-by-path map), it is ok for a SqmFrom to replace a
// non-SqmFrom. This should equate to, e.g., an implicit join.

if ( sqmPath instanceof SqmFrom<?, ?> sqmFrom ) {
final var navigablePath = sqmPath.getNavigablePath();

if ( sqmPath instanceof SqmFrom<?, ?> sqmFrom ) {
registerByAliasOnly( sqmFrom );

final SqmFrom<?, ?> previousFromByPath = sqmFromByPath.put( sqmPath.getNavigablePath(), sqmFrom );

final var previousFromByPath = sqmFromByPath.put( navigablePath, sqmFrom );
if ( previousFromByPath != null ) {
// this should never happen
throw new ParsingException(
String.format(
Locale.ROOT,
"Registration for SqmFrom [%s] overrode previous registration: %s -> %s",
sqmPath.getNavigablePath(),
navigablePath,
previousFromByPath,
sqmFrom
)
);
}
}

final SqmPath<?> previousPath = sqmPathByPath.put( sqmPath.getNavigablePath(), sqmPath );

final var previousPath = sqmPathByPath.put( navigablePath, sqmPath );
if ( previousPath instanceof SqmFrom ) {
// this should never happen
throw new ParsingException(
String.format(
Locale.ROOT,
"Registration for path [%s] overrode previous registration: %s -> %s",
sqmPath.getNavigablePath(),
navigablePath,
previousPath,
sqmPath
)
Expand All @@ -101,8 +107,6 @@ public void register(SqmPath<?> sqmPath) {

private static String fromPath(SqmFrom<?, ?> sqmFrom, boolean first) {
//TODO: the qualified path, but not using getFullPath() which has cruft
final String path = sqmFrom.getNavigablePath().getLocalName();
final String alias = sqmFrom.getExplicitAlias();
final String keyword;
if ( sqmFrom instanceof SqmRoot && first ) {
keyword = "from ";
Expand All @@ -113,19 +117,16 @@ else if ( sqmFrom instanceof SqmJoin ) {
else {
keyword = first ? "" : ", ";
}
final String path = sqmFrom.getNavigablePath().getLocalName();
final String alias = sqmFrom.getExplicitAlias();
return keyword + (alias == null ? path : path + " as " + alias);
}

@Override
public void registerByAliasOnly(SqmFrom<?, ?> sqmFrom) {
final String alias = sqmFrom.getExplicitAlias();
if ( alias != null ) {
final String aliasToUse = jpaCompliance.isJpaQueryComplianceEnabled()
? alias.toLowerCase( Locale.getDefault() )
: alias;

final SqmFrom<?, ?> previousFrom = sqmFromByAlias.put( aliasToUse, sqmFrom );

final var previousFrom = sqmFromByAlias.put( handleAliasCaseSensitivity( alias ), sqmFrom );
if ( previousFrom != null ) {
throw new AliasCollisionException(
String.format(
Expand All @@ -144,11 +145,7 @@ public void registerByAliasOnly(SqmFrom<?, ?> sqmFrom) {
public <E> void replace(SqmEntityJoin<?,E> sqmJoin, SqmRoot<E> sqmRoot) {
final String alias = sqmJoin.getExplicitAlias();
if ( alias != null ) {
final String aliasToUse = jpaCompliance.isJpaQueryComplianceEnabled()
? alias.toLowerCase( Locale.getDefault() )
: alias;

final SqmFrom<?, ?> previousFrom = sqmFromByAlias.put( aliasToUse, sqmJoin );
final var previousFrom = sqmFromByAlias.put( handleAliasCaseSensitivity( alias ), sqmJoin );
if ( previousFrom != null && !( previousFrom instanceof SqmRoot ) ) {
throw new AliasCollisionException(
String.format(
Expand All @@ -162,28 +159,30 @@ public <E> void replace(SqmEntityJoin<?,E> sqmJoin, SqmRoot<E> sqmRoot) {
}
}

final SqmFrom<?, ?> previousFromByPath = sqmFromByPath.put( sqmJoin.getNavigablePath(), sqmJoin );
final var navigablePath = sqmJoin.getNavigablePath();

final var previousFromByPath = sqmFromByPath.put( navigablePath, sqmJoin );
if ( previousFromByPath != null && !( previousFromByPath instanceof SqmRoot ) ) {
// this should never happen
throw new ParsingException(
String.format(
Locale.ROOT,
"Registration for SqmFrom [%s] overrode previous registration: %s -> %s",
sqmJoin.getNavigablePath(),
navigablePath,
previousFromByPath,
sqmJoin
)
);
}

final SqmPath<?> previousPath = sqmPathByPath.put( sqmJoin.getNavigablePath(), sqmJoin );
final var previousPath = sqmPathByPath.put( navigablePath, sqmJoin );
if ( previousPath instanceof SqmFrom && !( previousPath instanceof SqmRoot ) ) {
// this should never happen
throw new ParsingException(
String.format(
Locale.ROOT,
"Registration for path [%s] overrode previous registration: %s -> %s",
sqmJoin.getNavigablePath(),
navigablePath,
previousPath,
sqmJoin
)
Expand All @@ -199,58 +198,57 @@ public <E> void replace(SqmEntityJoin<?,E> sqmJoin, SqmRoot<E> sqmRoot) {

@Override
public <X extends SqmFrom<?, ?>> X findFromByAlias(String alias, boolean searchParent) {
final String localAlias = jpaCompliance.isJpaQueryComplianceEnabled()
? alias.toLowerCase( Locale.getDefault() )
: alias;

final SqmFrom<?, ?> registered = sqmFromByAlias.get( localAlias );
final String localAlias = handleAliasCaseSensitivity( alias );

final var registered = sqmFromByAlias.get( localAlias );
if ( registered != null ) {
//noinspection unchecked
return (X) registered;
}

SqmCreationProcessingState parentProcessingState = associatedProcessingState.getParentProcessingState();
var parentProcessingState = associatedProcessingState.getParentProcessingState();
if ( searchParent && parentProcessingState != null ) {
X parentRegistered;
do {
parentRegistered = parentProcessingState.getPathRegistry().findFromByAlias(
alias,
false
);
parentRegistered =
parentProcessingState.getPathRegistry()
.findFromByAlias( alias, false );
parentProcessingState = parentProcessingState.getParentProcessingState();
} while (parentProcessingState != null && parentRegistered == null);
}
while (parentProcessingState != null && parentRegistered == null);
if ( parentRegistered != null ) {
// If a parent query contains the alias, we need to create a correlation on the subquery
final SqmSubQuery<?> selectQuery = ( SqmSubQuery<?> ) associatedProcessingState.getProcessingQuery();
final SqmFrom<?, ?> correlated;
if ( parentRegistered instanceof Root<?> root ) {
correlated = selectQuery.correlate( root );
}
else if ( parentRegistered instanceof Join<?, ?> join ) {
correlated = selectQuery.correlate( join );
}
else {
throw new UnsupportedOperationException( "Can't correlate from node: " + parentRegistered );
}
final var correlated = correlate( parentRegistered );
register( correlated );
//noinspection unchecked
return (X) correlated;
}
}

final boolean onlyOneFrom = sqmFromByPath.size() == 1;
if ( onlyOneFrom && localAlias.equals( "this" ) ) {
final SqmRoot<?> root = (SqmRoot<?>) sqmFromByPath.entrySet().iterator().next().getValue();
if ( onlyOneFrom && localAlias.equalsIgnoreCase( "this" ) ) {
final var root = (SqmRoot<?>) sqmFromByPath.entrySet().iterator().next().getValue();
if ( root.getAlias() == null ) {
//noinspection unchecked
return (X) root;
}
}

return null;
}

private <X extends SqmFrom<?, ?>> SqmFrom<?, ?> correlate(X parentRegistered) {
final var selectQuery = (SqmSubQuery<?>) associatedProcessingState.getProcessingQuery();
if ( parentRegistered instanceof Root<?> root ) {
return selectQuery.correlate( root );
}
else if ( parentRegistered instanceof Join<?, ?> join ) {
return selectQuery.correlate( join );
}
else {
throw new UnsupportedOperationException( "Can't correlate from node: " + parentRegistered );
}
}

@Override
public <X extends SqmFrom<?, ?>> X findFromExposing(String navigableName) {
// todo (6.0) : atm this checks every from-element every time, the idea being to make sure there
Expand All @@ -259,7 +257,7 @@ else if ( parentRegistered instanceof Join<?, ?> join ) {

SqmFrom<?, ?> found = null;
for ( var entry : sqmFromByPath.entrySet() ) {
final SqmFrom<?, ?> fromElement = entry.getValue();
final var fromElement = entry.getValue();
if ( definesAttribute( fromElement.getReferencedPathSource(), navigableName ) ) {
if ( found != null ) {
throw new SemanticException( "Ambiguous unqualified attribute reference '" + navigableName +
Expand All @@ -270,12 +268,13 @@ else if ( parentRegistered instanceof Join<?, ?> join ) {
}

if ( found == null ) {
if ( associatedProcessingState.getParentProcessingState() != null ) {
final var processingState = associatedProcessingState.getParentProcessingState();
if ( processingState != null ) {
// QUERY_LOGGER.tracef(
// "Unable to resolve unqualified attribute [%s] in local from-clause; checking parent ",
// navigableName
// );
found = associatedProcessingState.getParentProcessingState().getPathRegistry().findFromExposing( navigableName );
found = processingState.getPathRegistry().findFromExposing( navigableName );
}
}

Expand All @@ -290,83 +289,76 @@ else if ( parentRegistered instanceof Join<?, ?> join ) {

@Override
public <X extends SqmFrom<?, ?>> X resolveFrom(NavigablePath navigablePath, Function<NavigablePath, SqmFrom<?, ?>> creator) {
final SqmFrom<?, ?> existing = sqmFromByPath.get( navigablePath );
final var existing = sqmFromByPath.get( navigablePath );
if ( existing != null ) {
//noinspection unchecked
return (X) existing;
}

final SqmFrom<?, ?> sqmFrom = creator.apply( navigablePath );
register( sqmFrom );
//noinspection unchecked
return (X) sqmFrom;
else {
final var sqmFrom = creator.apply( navigablePath );
register( sqmFrom );
//noinspection unchecked
return (X) sqmFrom;
}
}

@Override
public <X extends SqmFrom<?, ?>> X resolveFrom(SqmPath<?> path) {
final SqmFrom<?, ?> existing = sqmFromByPath.get( path.getNavigablePath() );
final var navigablePath = path.getNavigablePath();
final var existing = sqmFromByPath.get( navigablePath );
if ( existing != null ) {
//noinspection unchecked
return (X) existing;
}

final SqmFrom<?, ?> sqmFrom = resolveFrom( path.getLhs() ).join( path.getNavigablePath().getLocalName() );
register( sqmFrom );
//noinspection unchecked
return (X) sqmFrom;
else {
final var sqmFrom =
resolveFrom( path.getLhs() )
.join( navigablePath.getLocalName() );
register( sqmFrom );
//noinspection unchecked
return (X) sqmFrom;
}
}

private boolean definesAttribute(SqmPathSource<?> containerType, String name) {
return !( containerType.getSqmType() instanceof BasicDomainType )
&& containerType.findSubPathSource( name, true ) != null;
&& containerType.findSubPathSource( name, true ) != null;
}

@Override
public SqmAliasedNode<?> findAliasedNodeByAlias(String alias) {
assert alias != null;

final String aliasToUse = jpaCompliance.isJpaQueryComplianceEnabled()
? alias.toLowerCase( Locale.getDefault() )
: alias;

final String aliasToUse = handleAliasCaseSensitivity( alias );
for ( int i = 0; i < simpleSelectionNodes.size(); i++ ) {
final SqmAliasedNode<?> node = simpleSelectionNodes.get( i );
final var node = simpleSelectionNodes.get( i );
if ( aliasToUse.equals( node.getAlias() ) ) {
return node;
}
}

return null;
}

@Override
public Integer findAliasedNodePosition(String alias) {
if ( alias == null ) {
return null;
}

final String aliasToUse = jpaCompliance.isJpaQueryComplianceEnabled()
? alias.toLowerCase( Locale.getDefault() )
: alias;

// NOTE : 1-based

for ( int i = 0; i < simpleSelectionNodes.size(); i++ ) {
final SqmAliasedNode<?> node = simpleSelectionNodes.get( i );
if ( aliasToUse.equals( node.getAlias() ) ) {
return i + 1;
if ( alias != null ) {
final String aliasToUse = handleAliasCaseSensitivity( alias );
// NOTE: 1-based
for ( int i = 0; i < simpleSelectionNodes.size(); i++ ) {
final var node = simpleSelectionNodes.get( i );
if ( aliasToUse.equals( node.getAlias() ) ) {
return i + 1;
}
}
}

return null;
}

@Override
public SqmAliasedNode<?> findAliasedNodeByPosition(int position) {
// NOTE : 1-based
// NOTE: 1-based
return position > simpleSelectionNodes.size()
? null
: simpleSelectionNodes.get(position - 1);
: simpleSelectionNodes.get( position - 1 );
}

@Override
Expand All @@ -377,20 +369,18 @@ public void register(SqmAliasedNode<?> node) {

private void checkResultVariable(SqmAliasedNode<?> selection) {
final String alias = selection.getAlias();
if ( alias == null ) {
return;
}

final Integer position = findAliasedNodePosition( alias );
if ( position != null ) {
throw new AliasCollisionException(
String.format(
Locale.ENGLISH,
"Duplicate alias '%s' at position %s in 'select' clause",
alias,
position
)
);
if ( alias != null ) {
final Integer position = findAliasedNodePosition( alias );
if ( position != null ) {
throw new AliasCollisionException(
String.format(
Locale.ENGLISH,
"Duplicate alias '%s' at position %s in 'select' clause",
alias,
position
)
);
}
}
}
}
Loading