Disallow FQN as entity name in Jpa compliance mode

This commit is contained in:
Nathan Xu 2020-02-02 16:06:51 -05:00 committed by Steve Ebersole
parent c97fb45a02
commit 60ead26c4b
3 changed files with 58 additions and 3 deletions

View File

@ -167,7 +167,6 @@ import static java.util.Collections.singletonList;
import static org.hibernate.grammars.hql.HqlParser.IDENTIFIER;
import static org.hibernate.query.TemporalUnit.*;
import static org.hibernate.type.descriptor.DateTimeUtils.DATE_TIME;
import static org.hibernate.type.descriptor.DateTimeUtils.OFFSET_DATE_TIME;
import static org.hibernate.type.spi.TypeConfiguration.isJdbcTemporalType;
/**
@ -264,7 +263,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// To-level statements
// Top-level statements
@Override
public SqmSelectStatement visitSelectStatement(HqlParser.SelectStatementContext ctx) {
@ -828,7 +827,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
if ( entityReference == null ) {
throw new UnknownEntityException( "Could not resolve entity name [" + entityName + "] as DML target", entityName );
}
checkFQNEntityNameJpaComplianceViolationIfNeeded( entityName, entityReference );
return entityReference;
}
@ -895,6 +894,8 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
name
);
checkFQNEntityNameJpaComplianceViolationIfNeeded( name, entityDescriptor );
if ( entityDescriptor instanceof SqmPolymorphicRootDescriptor ) {
if ( getCreationOptions().useStrictJpaCompliance() ) {
throw new StrictJpaComplianceViolation(
@ -3510,4 +3511,14 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
throw new NotYetImplementedFor6Exception();
}
}
private void checkFQNEntityNameJpaComplianceViolationIfNeeded(String name, EntityDomainType entityDescriptor) {
if ( getCreationOptions().useStrictJpaCompliance() && ! name.equals( entityDescriptor.getName() ) ) {
// FQN is the only possible reason
throw new StrictJpaComplianceViolation("Encountered FQN entity name [" + name + "], " +
"but strict JPQL compliance was requested ( [" + entityDescriptor.getName() + "] should be used instead )",
StrictJpaComplianceViolation.Type.FQN_ENTITY_NAME
);
}
}
}

View File

@ -26,6 +26,7 @@ public class StrictJpaComplianceViolation extends SemanticException {
SUBQUERY_ORDER_BY( "use of ORDER BY clause in subquery" ),
LIMIT_OFFSET_CLAUSE( "use of LIMIT/OFFSET clause" ),
IDENTIFICATION_VARIABLE_NOT_DECLARED_IN_FROM_CLAUSE( "use of an alias not declared in the FROM clause" ),
FQN_ENTITY_NAME( "use of FQN for entity name" ),
;
private final String description;

View File

@ -0,0 +1,43 @@
package org.hibernate.orm.test.query.hql;
import org.hibernate.orm.test.query.sqm.BaseSqmUnitTest;
import org.hibernate.orm.test.query.sqm.domain.Person;
import org.hibernate.query.sqm.StrictJpaComplianceViolation;
import org.hibernate.testing.orm.junit.ExpectedException;
import org.junit.jupiter.api.Test;
/**
* @author Nahtan Xu
*/
@SuppressWarnings("WeakerAccess")
public class JpaComplianceDisallowFQNTests extends BaseSqmUnitTest {
@Override
protected boolean strictJpaCompliance() {
return true;
}
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] { Person.class };
}
@Test
@ExpectedException(StrictJpaComplianceViolation.class)
public void testQuery() {
interpretSelect( String.format( "select p from %s p", Person.class.getName() ) );
}
@Test
@ExpectedException(StrictJpaComplianceViolation.class)
public void testUpdate() {
interpretSelect( String.format( "update %s set numberOfToes = 0", Person.class.getName() ) );
}
@Test
@ExpectedException(StrictJpaComplianceViolation.class)
public void testDelete() {
interpretSelect( String.format( "delete %s", Person.class.getName() ) );
}
}