Skip to content
Merged
Show file tree
Hide file tree
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 @@ -542,7 +542,7 @@ Hibernate does support a means to refer specifically to the key column (`Person.
using the special `fk(..)` function. E.g.

[[associations-not-found-fk-function-example]]
.Implicit join example
.FK example
====
[source,java]
----
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ private AttributeJoinDelegate resolveAlias(String identifier, boolean isTerminal
if ( allowReuse ) {
if ( !isTerminal ) {
for ( SqmJoin<?, ?> sqmJoin : lhs.getSqmJoins() ) {
if ( sqmJoin.getAlias() == null && sqmJoin.getReferencedPathSource() == subPathSource ) {
if ( sqmJoin.getAlias() == null && sqmJoin.getModel() == subPathSource ) {
return sqmJoin;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@
import org.hibernate.query.sqm.tree.domain.SqmCteRoot;
import org.hibernate.query.sqm.tree.domain.SqmDerivedRoot;
import org.hibernate.query.sqm.tree.domain.SqmElementAggregateFunction;
import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmFkExpression;
import org.hibernate.query.sqm.tree.domain.SqmFunctionRoot;
import org.hibernate.query.sqm.tree.domain.SqmIndexAggregateFunction;
Expand Down Expand Up @@ -3579,7 +3578,7 @@ public SqmFkExpression<?> visitToOneFkReference(HqlParser.ToOneFkReferenceContex
);

}
return new SqmFkExpression<>( (SqmEntityValuedSimplePath<?>) sqmPath );
return new SqmFkExpression<>( sqmPath );
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.Set;
Expand All @@ -45,6 +46,7 @@
import org.hibernate.metamodel.model.domain.JpaMetamodel;
import org.hibernate.metamodel.model.domain.PersistentAttribute;
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
import org.hibernate.metamodel.model.domain.internal.EntitySqmPathSource;
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
import org.hibernate.query.BindableType;
import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode;
Expand Down Expand Up @@ -98,7 +100,6 @@
import org.hibernate.query.sqm.tree.cte.SqmSearchClauseSpecification;
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
import org.hibernate.query.sqm.tree.domain.SqmBagJoin;
import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmFkExpression;
import org.hibernate.query.sqm.tree.domain.SqmListJoin;
import org.hibernate.query.sqm.tree.domain.SqmMapJoin;
Expand Down Expand Up @@ -595,12 +596,22 @@ public <T extends HibernateCriteriaBuilder> T unwrap(Class<T> clazz) {

@Override
public <P, F> SqmExpression<F> fk(Path<P> path) {
if ( path.getModel().getBindableType() != Bindable.BindableType.SINGULAR_ATTRIBUTE
|| ! ( path instanceof SqmEntityValuedSimplePath ) ) {
throw new FunctionArgumentException( "Path '" + path + "' does not refer to a single-valued association" );
final SqmPath<P> sqmPath = (SqmPath<P>) path;
final SqmPathSource<?> toOneReference = sqmPath.getReferencedPathSource();
final boolean validToOneRef =
toOneReference.getBindableType() == Bindable.BindableType.SINGULAR_ATTRIBUTE
&& toOneReference instanceof EntitySqmPathSource;
if ( !validToOneRef ) {
throw new FunctionArgumentException(
String.format(
Locale.ROOT,
"Argument '%s' of 'fk()' function is not a single-valued association",
sqmPath.getNavigablePath()
)
);
}

return new SqmFkExpression<>( (SqmEntityValuedSimplePath<?>) path );
return new SqmFkExpression<>( sqmPath );
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -745,7 +745,7 @@ public Object visitNonAggregatedCompositeValuedPath(NonAggregatedCompositeSimple

@Override
public Object visitFkExpression(SqmFkExpression<?> fkExpression) {
logWithIndentation( "-> [fk-ref] - `%s`", fkExpression.getToOnePath().getNavigablePath() );
logWithIndentation( "-> [fk-ref] - `%s`", fkExpression.getLhs().getNavigablePath() );

return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ public static <T, A> SqmAttributeJoin<T, A> findCompatibleFetchJoin(
SqmPathSource<A> pathSource,
SqmJoinType requestedJoinType) {
for ( final SqmJoin<T, ?> join : sqmFrom.getSqmJoins() ) {
if ( join.getReferencedPathSource() == pathSource ) {
if ( join.getModel() == pathSource ) {
final SqmAttributeJoin<T, ?> attributeJoin = (SqmAttributeJoin<T, ?>) join;
if ( attributeJoin.isFetched() ) {
final SqmJoinType joinType = join.getSqmJoinType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4567,11 +4567,12 @@ public Expression visitPluralValuedPath(SqmPluralValuedSimplePath<?> sqmPath) {

@Override
public Object visitFkExpression(SqmFkExpression<?> fkExpression) {
final SqmPath<?> lhs = fkExpression.getToOnePath().getLhs();
final SqmPath<?> toOnePath = fkExpression.getLhs();
final SqmPath<?> lhs = toOnePath.getLhs();
prepareReusablePath( lhs, () -> null );
final TableGroup tableGroup = getFromClauseIndex().findTableGroup( lhs.getNavigablePath() );
final ModelPart subPart = tableGroup.getModelPart()
.findSubPart( fkExpression.getToOnePath().getModel().getPathName(), null );
.findSubPart( toOnePath.getReferencedPathSource().getPathName(), null );
assert subPart instanceof ToOneAttributeMapping;

final ToOneAttributeMapping toOneMapping = (ToOneAttributeMapping) subPart;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public <X> X accept(SemanticQueryWalker<X> walker) {
@Override
public PersistentAttribute<? super L, ?> getAttribute() {
//noinspection unchecked
return (PersistentAttribute<? super L, ?>) getReferencedPathSource();
return (PersistentAttribute<? super L, ?>) getModel();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package org.hibernate.query.sqm.tree.domain;

import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.metamodel.model.domain.IdentifiableDomainType;
import org.hibernate.query.hql.spi.SqmCreationState;
Expand All @@ -21,15 +22,14 @@
* @author Steve Ebersole
*/
public class SqmFkExpression<T> extends AbstractSqmPath<T> {

public SqmFkExpression(SqmEntityValuedSimplePath<?> toOnePath) {
public SqmFkExpression(SqmPath<?> toOnePath) {
this( toOnePath.getNavigablePath().append( ForeignKeyDescriptor.PART_NAME ), toOnePath );
}

@SuppressWarnings("unchecked")
private SqmFkExpression(
NavigablePath navigablePath,
SqmEntityValuedSimplePath<?> toOnePath) {
SqmPath<?> toOnePath) {
super(
navigablePath,
(SqmPathSource<T>) pathDomainType( toOnePath ).getIdentifierDescriptor(),
Expand All @@ -38,12 +38,14 @@ private SqmFkExpression(
);
}

private static IdentifiableDomainType<?> pathDomainType(SqmEntityValuedSimplePath<?> toOnePath) {
return (IdentifiableDomainType<?>) toOnePath.getNodeType();
}

public SqmEntityValuedSimplePath<?> getToOnePath() {
return (SqmEntityValuedSimplePath<?>) getLhs();
private static IdentifiableDomainType<?> pathDomainType(SqmPath<?> toOnePath) {
final DomainType<?> domainType = toOnePath.getReferencedPathSource().getSqmPathType();
if ( domainType instanceof IdentifiableDomainType<?> identifiableDomainType ) {
return identifiableDomainType;
}
else {
throw new IllegalArgumentException( "Invalid path provided to 'fk()' function: " + toOnePath.getNavigablePath() );
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
import org.hibernate.metamodel.model.domain.TreatableDomainType;
import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.spi.NavigablePath;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.tree.SqmCopyContext;
Expand Down Expand Up @@ -80,6 +81,16 @@ public SqmSingularJoin<O, T> copy(SqmCopyContext context) {
return path;
}

@Override
public SqmPathSource<T> getNodeType() {
return getReferencedPathSource();
}

@Override
public SqmPathSource<T> getReferencedPathSource() {
return getModel().getPathSource();
}

@Override
public SingularPersistentAttribute<O, T> getModel() {
return (SingularPersistentAttribute<O, T>) super.getNodeType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public void queryTestFk(EntityManagerFactoryScope scope) {
assertThat( nullResults ).isEmpty();

final List<String> nonNullResults = entityManager
.createQuery( "select p.name from Person p where fk( p.city ) is not null", String.class )
.createQuery( "select p.name from Person p left join p.city c where fk( c ) is not null", String.class )
.getResultList();
assertThat( nonNullResults ).hasSize( 1 );
assertThat( nonNullResults.get( 0 ) ).isEqualTo( "John Doe" );
Expand Down
Loading
Loading