mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-08 12:14:47 +00:00
support for canonical reference to id and version. consider other entity parts - natural-id, tenant-discriminator, etc
This commit is contained in:
parent
c2bb7d65f2
commit
b23e5ba54a
@ -141,6 +141,10 @@ ARROW : '->';
|
|||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// Keywords
|
// Keywords
|
||||||
|
|
||||||
|
ID : [iI][dD];
|
||||||
|
VERSION : [vV] [eE] [rR] [sS] [iI] [oO] [nN];
|
||||||
|
NATURALID : [nN] [aA] [tT] [uU] [rR] [aA] [lL] [iI] [dD];
|
||||||
|
|
||||||
ABS : [aA] [bB] [sS];
|
ABS : [aA] [bB] [sS];
|
||||||
ALL : [aA] [lL] [lL];
|
ALL : [aA] [lL] [lL];
|
||||||
AND : [aA] [nN] [dD];
|
AND : [aA] [nN] [dD];
|
||||||
|
@ -413,6 +413,9 @@ expression
|
|||||||
| literal # LiteralExpression
|
| literal # LiteralExpression
|
||||||
| parameter # ParameterExpression
|
| parameter # ParameterExpression
|
||||||
| entityTypeReference # EntityTypeExpression
|
| entityTypeReference # EntityTypeExpression
|
||||||
|
| entityIdReference # EntityIdExpression
|
||||||
|
| entityVersionReference # EntityVersionExpression
|
||||||
|
| entityNaturalIdReference # EntityNaturalIdExpression
|
||||||
| path # PathExpression
|
| path # PathExpression
|
||||||
| function # FunctionExpression
|
| function # FunctionExpression
|
||||||
| LEFT_PAREN subQuery RIGHT_PAREN # SubQueryExpression
|
| LEFT_PAREN subQuery RIGHT_PAREN # SubQueryExpression
|
||||||
@ -422,6 +425,18 @@ entityTypeReference
|
|||||||
: TYPE LEFT_PAREN (path | parameter) RIGHT_PAREN
|
: TYPE LEFT_PAREN (path | parameter) RIGHT_PAREN
|
||||||
;
|
;
|
||||||
|
|
||||||
|
entityIdReference
|
||||||
|
: ID LEFT_PAREN path RIGHT_PAREN pathContinuation?
|
||||||
|
;
|
||||||
|
|
||||||
|
entityVersionReference
|
||||||
|
: VERSION LEFT_PAREN path RIGHT_PAREN
|
||||||
|
;
|
||||||
|
|
||||||
|
entityNaturalIdReference
|
||||||
|
: NATURALID LEFT_PAREN path RIGHT_PAREN pathContinuation?
|
||||||
|
;
|
||||||
|
|
||||||
caseStatement
|
caseStatement
|
||||||
: simpleCaseStatement
|
: simpleCaseStatement
|
||||||
| searchedCaseStatement
|
| searchedCaseStatement
|
||||||
@ -987,6 +1002,7 @@ identifier
|
|||||||
| GREATEST
|
| GREATEST
|
||||||
| GROUP
|
| GROUP
|
||||||
| HOUR
|
| HOUR
|
||||||
|
| ID
|
||||||
| IFNULL
|
| IFNULL
|
||||||
| IN
|
| IN
|
||||||
| INDEX
|
| INDEX
|
||||||
@ -1020,6 +1036,7 @@ identifier
|
|||||||
| MOD
|
| MOD
|
||||||
| MONTH
|
| MONTH
|
||||||
| NANOSECOND
|
| NANOSECOND
|
||||||
|
| NATURALID
|
||||||
| NEW
|
| NEW
|
||||||
| NOT
|
| NOT
|
||||||
| NULLIF
|
| NULLIF
|
||||||
@ -1056,6 +1073,7 @@ identifier
|
|||||||
| UPDATE
|
| UPDATE
|
||||||
| UPPER
|
| UPPER
|
||||||
| VALUE
|
| VALUE
|
||||||
|
| VERSION
|
||||||
| WEEK
|
| WEEK
|
||||||
| WHERE
|
| WHERE
|
||||||
| WITH
|
| WITH
|
||||||
|
@ -39,11 +39,13 @@
|
|||||||
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||||
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||||
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
||||||
|
import org.hibernate.metamodel.model.domain.DomainType;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.IdentifiableDomainType;
|
import org.hibernate.metamodel.model.domain.IdentifiableDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.MapPersistentAttribute;
|
import org.hibernate.metamodel.model.domain.MapPersistentAttribute;
|
||||||
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
|
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
|
||||||
|
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
||||||
import org.hibernate.query.BinaryArithmeticOperator;
|
import org.hibernate.query.BinaryArithmeticOperator;
|
||||||
import org.hibernate.query.ComparisonOperator;
|
import org.hibernate.query.ComparisonOperator;
|
||||||
import org.hibernate.query.PathException;
|
import org.hibernate.query.PathException;
|
||||||
@ -1320,6 +1322,70 @@ else if ( ctx.entityTypeReference().path() != null ) {
|
|||||||
throw new ParsingException( "Could not interpret grammar context as 'entity type' expression : " + ctx.getText() );
|
throw new ParsingException( "Could not interpret grammar context as 'entity type' expression : " + ctx.getText() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmPath visitEntityIdExpression(HqlParser.EntityIdExpressionContext ctx) {
|
||||||
|
return visitEntityIdReference( ctx.entityIdReference() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmPath visitEntityIdReference(HqlParser.EntityIdReferenceContext ctx) {
|
||||||
|
final SqmPath sqmPath = consumeDomainPath( ctx.path() );
|
||||||
|
final DomainType sqmPathType = sqmPath.getReferencedPathSource().getSqmPathType();
|
||||||
|
|
||||||
|
if ( sqmPathType instanceof IdentifiableDomainType ) {
|
||||||
|
//noinspection unchecked
|
||||||
|
final SqmPath idPath = ( (IdentifiableDomainType) sqmPathType ).getIdentifierDescriptor().createSqmPath(
|
||||||
|
sqmPath,
|
||||||
|
this
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( ctx.pathContinuation() == null ) {
|
||||||
|
return idPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NotYetImplementedFor6Exception( "Path continuation from `id()` reference not yet implemented" );
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new SemanticException( "Path does not reference an identifiable-type : " + sqmPath.getNavigablePath().getFullPath() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmPath visitEntityVersionExpression(HqlParser.EntityVersionExpressionContext ctx) {
|
||||||
|
return visitEntityVersionReference( ctx.entityVersionReference() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmPath visitEntityVersionReference(HqlParser.EntityVersionReferenceContext ctx) {
|
||||||
|
final SqmPath sqmPath = consumeDomainPath( ctx.path() );
|
||||||
|
final DomainType sqmPathType = sqmPath.getReferencedPathSource().getSqmPathType();
|
||||||
|
|
||||||
|
if ( sqmPathType instanceof IdentifiableDomainType ) {
|
||||||
|
final IdentifiableDomainType identifiableType = (IdentifiableDomainType) sqmPathType;
|
||||||
|
final SingularPersistentAttribute versionAttribute = identifiableType.findVersionAttribute();
|
||||||
|
if ( versionAttribute == null ) {
|
||||||
|
throw new SemanticException(
|
||||||
|
"`" + sqmPath.getNavigablePath().getFullPath() + "` resolved to an identifiable-type (`" +
|
||||||
|
identifiableType.getTypeName() + "`) which does not define a version"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//noinspection unchecked
|
||||||
|
return versionAttribute.createSqmPath( sqmPath, this );
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new SemanticException( "Path does not reference an identifiable-type : " + sqmPath.getNavigablePath().getFullPath() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmPath visitEntityNaturalIdExpression(HqlParser.EntityNaturalIdExpressionContext ctx) {
|
||||||
|
return visitEntityNaturalIdReference( ctx.entityNaturalIdReference() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmPath visitEntityNaturalIdReference(HqlParser.EntityNaturalIdReferenceContext ctx) {
|
||||||
|
throw new NotYetImplementedFor6Exception( "Support for HQL natural-id references not yet implemented" );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public SqmMapEntryReference visitMapEntrySelection(HqlParser.MapEntrySelectionContext ctx) {
|
public SqmMapEntryReference visitMapEntrySelection(HqlParser.MapEntrySelectionContext ctx) {
|
||||||
@ -3551,7 +3617,6 @@ public SqmPath visitMapKeyNavigablePath(HqlParser.MapKeyNavigablePathContext ctx
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private SqmPath consumeDomainPath(HqlParser.PathContext parserPath) {
|
private SqmPath consumeDomainPath(HqlParser.PathContext parserPath) {
|
||||||
final SemanticPathPart consumedPart = (SemanticPathPart) parserPath.accept( this );
|
final SemanticPathPart consumedPart = (SemanticPathPart) parserPath.accept( this );
|
||||||
if ( consumedPart instanceof SqmPath ) {
|
if ( consumedPart instanceof SqmPath ) {
|
||||||
|
@ -7,18 +7,16 @@
|
|||||||
package org.hibernate.orm.test.query.hql;
|
package org.hibernate.orm.test.query.hql;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
|
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
||||||
import org.hibernate.metamodel.model.domain.internal.SingularAttributeImpl;
|
|
||||||
import org.hibernate.orm.test.query.sqm.BaseSqmUnitTest;
|
import org.hibernate.orm.test.query.sqm.BaseSqmUnitTest;
|
||||||
import org.hibernate.orm.test.query.sqm.domain.Person;
|
import org.hibernate.orm.test.query.sqm.domain.Person;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath;
|
import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmSimplePath;
|
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
|
import org.hibernate.query.sqm.tree.domain.SqmSimplePath;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
|
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
|
||||||
@ -29,8 +27,6 @@
|
|||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.hamcrest.CoreMatchers;
|
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||||
import static org.hamcrest.CoreMatchers.is;
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
import static org.hamcrest.CoreMatchers.not;
|
import static org.hamcrest.CoreMatchers.not;
|
||||||
@ -112,8 +108,6 @@ public void testEntityIdReferences() {
|
|||||||
interpretSelect( "select s.mate from Person s where s.id = ?1" );
|
interpretSelect( "select s.mate from Person s where s.id = ?1" );
|
||||||
interpretSelect( "select s.mate from Person s where s.pk = ?1" );
|
interpretSelect( "select s.mate from Person s where s.pk = ?1" );
|
||||||
|
|
||||||
// NOTE: this next form does not (yet) work...
|
|
||||||
interpretSelect( "select s.mate from Person s where s.{id} = ?1" );
|
|
||||||
|
|
||||||
final EntityDomainType<OddOne> entity = sessionFactory().getRuntimeMetamodels()
|
final EntityDomainType<OddOne> entity = sessionFactory().getRuntimeMetamodels()
|
||||||
.getJpaMetamodel()
|
.getJpaMetamodel()
|
||||||
@ -131,6 +125,14 @@ public void testEntityIdReferences() {
|
|||||||
assertThat( ( (SqmPath) pkRef ).getJavaType(), sameInstance( String.class ) );
|
assertThat( ( (SqmPath) pkRef ).getJavaType(), sameInstance( String.class ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCanonicalReferences() {
|
||||||
|
final SqmSelectStatement sqm = interpretSelect( "select s.mate from Person s where id(s) = ?1" );
|
||||||
|
assertThat( sqm.getQuerySpec().getRestriction(), notNullValue() );
|
||||||
|
final SqmComparisonPredicate restriction = (SqmComparisonPredicate) sqm.getQuerySpec().getRestriction();
|
||||||
|
assertThat( restriction, notNullValue() );
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testManyToOneReference() {
|
public void testManyToOneReference() {
|
||||||
final SqmSelectStatement sqm = interpretSelect( "select s.mate from Person s" );
|
final SqmSelectStatement sqm = interpretSelect( "select s.mate from Person s" );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user