HHH-16732 make HQL id() function work for @Any mappings
This commit is contained in:
parent
2287f3ce3b
commit
8cc7eb7a66
|
@ -8,7 +8,6 @@ package org.hibernate.metamodel.mapping.internal;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.FetchStyle;
|
import org.hibernate.engine.FetchStyle;
|
||||||
|
|
|
@ -107,6 +107,7 @@ import org.hibernate.query.sqm.tree.cte.SqmCteContainer;
|
||||||
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
|
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
|
||||||
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||||
import org.hibernate.query.sqm.tree.domain.AbstractSqmFrom;
|
import org.hibernate.query.sqm.tree.domain.AbstractSqmFrom;
|
||||||
|
import org.hibernate.query.sqm.tree.domain.SqmAnyValuedSimplePath;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmCorrelation;
|
import org.hibernate.query.sqm.tree.domain.SqmCorrelation;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmCteRoot;
|
import org.hibernate.query.sqm.tree.domain.SqmCteRoot;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmDerivedRoot;
|
import org.hibernate.query.sqm.tree.domain.SqmDerivedRoot;
|
||||||
|
@ -2748,21 +2749,23 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmPath<?> visitEntityIdReference(HqlParser.EntityIdReferenceContext ctx) {
|
public SqmPath<?> visitEntityIdReference(HqlParser.EntityIdReferenceContext ctx) {
|
||||||
|
if ( ctx.getChildCount() == 5 ) {
|
||||||
|
throw new UnsupportedOperationException( "Path continuation from `id()` reference not yet implemented" );
|
||||||
|
}
|
||||||
|
|
||||||
final SqmPath<Object> sqmPath = consumeDomainPath( (HqlParser.PathContext) ctx.getChild( 2 ) );
|
final SqmPath<Object> sqmPath = consumeDomainPath( (HqlParser.PathContext) ctx.getChild( 2 ) );
|
||||||
final DomainType<?> sqmPathType = sqmPath.getReferencedPathSource().getSqmPathType();
|
final DomainType<?> sqmPathType = sqmPath.getReferencedPathSource().getSqmPathType();
|
||||||
|
|
||||||
if ( sqmPathType instanceof IdentifiableDomainType<?> ) {
|
if ( sqmPathType instanceof IdentifiableDomainType<?> ) {
|
||||||
final SqmPathSource<?> identifierDescriptor = ( (IdentifiableDomainType<?>) sqmPathType ).getIdentifierDescriptor();
|
final SqmPathSource<?> identifierDescriptor = ( (IdentifiableDomainType<?>) sqmPathType ).getIdentifierDescriptor();
|
||||||
final SqmPath<?> idPath = sqmPath.get( identifierDescriptor.getPathName() );
|
return sqmPath.get( identifierDescriptor.getPathName() );
|
||||||
|
}
|
||||||
if ( ctx.getChildCount() != 5 ) {
|
else if ( sqmPath instanceof SqmAnyValuedSimplePath<?> ) {
|
||||||
return idPath;
|
return sqmPath.resolvePathPart("id", true, getCurrentProcessingState().getCreationState() );
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
throw new UnsupportedOperationException( "Path continuation from `id()` reference not yet implemented" );
|
throw new SemanticException( "Path does not resolve to an entity type '" + sqmPath.getNavigablePath() + "'" );
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new SemanticException( "Path does not resolve to an entity type '" + sqmPath.getNavigablePath() + "'" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -22,19 +22,19 @@ import org.hibernate.MappingException;
|
||||||
import org.hibernate.PropertyNotFoundException;
|
import org.hibernate.PropertyNotFoundException;
|
||||||
import org.hibernate.TransientObjectException;
|
import org.hibernate.TransientObjectException;
|
||||||
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
|
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
|
||||||
import org.hibernate.engine.internal.ForeignKeys;
|
|
||||||
import org.hibernate.engine.spi.CascadeStyle;
|
import org.hibernate.engine.spi.CascadeStyle;
|
||||||
import org.hibernate.engine.spi.CascadeStyles;
|
import org.hibernate.engine.spi.CascadeStyles;
|
||||||
import org.hibernate.engine.spi.Mapping;
|
import org.hibernate.engine.spi.Mapping;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
|
||||||
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
|
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.entity.Joinable;
|
import org.hibernate.persister.entity.Joinable;
|
||||||
import org.hibernate.proxy.LazyInitializer;
|
import org.hibernate.proxy.LazyInitializer;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
import static org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved;
|
||||||
|
import static org.hibernate.internal.util.collections.ArrayHelper.join;
|
||||||
import static org.hibernate.pretty.MessageHelper.infoString;
|
import static org.hibernate.pretty.MessageHelper.infoString;
|
||||||
import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer;
|
import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer;
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getSqlTypeCodes(Mapping mapping) throws MappingException {
|
public int[] getSqlTypeCodes(Mapping mapping) throws MappingException {
|
||||||
return ArrayHelper.join( discriminatorType.getSqlTypeCodes( mapping ), identifierType.getSqlTypeCodes( mapping ) );
|
return join( discriminatorType.getSqlTypeCodes( mapping ), identifierType.getSqlTypeCodes( mapping ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -246,7 +246,7 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
entityName = session.bestGuessEntityName( value );
|
entityName = session.bestGuessEntityName( value );
|
||||||
id = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, value, session );
|
id = getEntityIdentifierIfNotUnsaved( entityName, value, session );
|
||||||
}
|
}
|
||||||
|
|
||||||
// discriminatorType is assumed to be single-column type
|
// discriminatorType is assumed to be single-column type
|
||||||
|
@ -295,7 +295,7 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
|
||||||
else {
|
else {
|
||||||
return new ObjectTypeCacheEntry(
|
return new ObjectTypeCacheEntry(
|
||||||
session.bestGuessEntityName( value ),
|
session.bestGuessEntityName( value ),
|
||||||
ForeignKeys.getEntityIdentifierIfNotUnsaved(
|
getEntityIdentifierIfNotUnsaved(
|
||||||
session.bestGuessEntityName( value ),
|
session.bestGuessEntityName( value ),
|
||||||
value,
|
value,
|
||||||
session
|
session
|
||||||
|
@ -317,7 +317,7 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
final String entityName = session.bestGuessEntityName( original );
|
final String entityName = session.bestGuessEntityName( original );
|
||||||
final Object id = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, original, session );
|
final Object id = getEntityIdentifierIfNotUnsaved( entityName, original, session );
|
||||||
return session.internalLoad( entityName, id, eager, false );
|
return session.internalLoad( entityName, id, eager, false );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -365,7 +365,7 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
|
||||||
|
|
||||||
private Object getIdentifier(Object value, SharedSessionContractImplementor session) throws HibernateException {
|
private Object getIdentifier(Object value, SharedSessionContractImplementor session) throws HibernateException {
|
||||||
try {
|
try {
|
||||||
return ForeignKeys.getEntityIdentifierIfNotUnsaved(
|
return getEntityIdentifierIfNotUnsaved(
|
||||||
session.bestGuessEntityName( value ),
|
session.bestGuessEntityName( value ),
|
||||||
value,
|
value,
|
||||||
session
|
session
|
||||||
|
@ -469,9 +469,10 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean equals(Object object) {
|
public boolean equals(Object object) {
|
||||||
if (object instanceof ObjectTypeCacheEntry) {
|
if ( object instanceof ObjectTypeCacheEntry ) {
|
||||||
ObjectTypeCacheEntry objectTypeCacheEntry = (ObjectTypeCacheEntry)object;
|
final ObjectTypeCacheEntry objectTypeCacheEntry = (ObjectTypeCacheEntry) object;
|
||||||
return Objects.equals( objectTypeCacheEntry.entityName, entityName ) && Objects.equals( objectTypeCacheEntry.id, id );
|
return Objects.equals( objectTypeCacheEntry.entityName, entityName )
|
||||||
|
&& Objects.equals( objectTypeCacheEntry.id, id );
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,6 +131,24 @@ public class AnyTest {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestForIssue( jiraKey = "HHH-16732")
|
||||||
|
public void testHqlAnyIdQuery(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
List<PropertySet> list1 = session.createQuery(
|
||||||
|
"select p from PropertyHolder p where id(p.property) = 666",
|
||||||
|
PropertySet.class ).list();
|
||||||
|
assertEquals( 0, list1.size() );
|
||||||
|
List<PropertySet> list2 = session.createQuery(
|
||||||
|
"select p from PropertyHolder p where type(p.property) = IntegerProperty",
|
||||||
|
PropertySet.class ).list();
|
||||||
|
assertEquals( 1, list2.size() );
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestForIssue( jiraKey = "HHH-15323")
|
@TestForIssue( jiraKey = "HHH-15323")
|
||||||
public void testHqlCollectionTypeQuery(SessionFactoryScope scope) {
|
public void testHqlCollectionTypeQuery(SessionFactoryScope scope) {
|
||||||
|
|
|
@ -82,6 +82,17 @@ public class EmbeddedAnyTest {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestForIssue( jiraKey = "HHH-16732")
|
||||||
|
public void testEmbeddedIdHql(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
final List<Foo> foos = session.createQuery( "from Foo f where id(f.fooEmbedded.bar) = 1", Foo.class )
|
||||||
|
.list();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestForIssue( jiraKey = "HHH-15323")
|
@TestForIssue( jiraKey = "HHH-15323")
|
||||||
public void testEmbeddedTypeHql(SessionFactoryScope scope) {
|
public void testEmbeddedTypeHql(SessionFactoryScope scope) {
|
||||||
|
|
Loading…
Reference in New Issue