correctly handle "weird" function names with periods and quotes in HQL

This commit is contained in:
Gavin King 2022-01-04 15:31:58 +01:00
parent b1aea5f993
commit 254d4d0351
3 changed files with 36 additions and 2 deletions

View File

@ -985,7 +985,9 @@ genericFunction
;
/**
* The name of a generic function
* The name of a generic function, which may contain periods and quoted identifiers
*
* Names of generic functions are resolved against the SqmFunctionRegistry
*/
genericFunctionName
: simplePath

View File

@ -3155,9 +3155,19 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
);
}
@Override
public String visitGenericFunctionName(HqlParser.GenericFunctionNameContext ctx) {
StringBuilder functionName = new StringBuilder( visitIdentifier( ctx.simplePath().identifier() ) );
for ( HqlParser.SimplePathElementContext sp: ctx.simplePath().simplePathElement() ) {
// allow function names of form foo.bar to be located in the registry
functionName.append('.').append( visitIdentifier( sp.identifier() ) );
}
return functionName.toString();
}
@Override
public Object visitGenericFunction(HqlParser.GenericFunctionContext ctx) {
final String originalFunctionName = ctx.getChild( 0 ).getText();
final String originalFunctionName = visitGenericFunctionName( ctx.genericFunctionName() );
final String functionName = originalFunctionName.toLowerCase();
if ( creationOptions.useStrictJpaCompliance() && !JPA_STANDARD_FUNCTIONS.contains( functionName ) ) {
throw new StrictJpaComplianceViolation(

View File

@ -9,6 +9,7 @@ package org.hibernate.orm.test.hql;
import java.util.List;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@ -46,6 +47,13 @@ public class QuotedIdentifierTest extends BaseCoreFunctionalTestCase {
} );
}
@After
public void tearDown() {
doInHibernate( this::sessionFactory, session -> {
session.createQuery("delete `The Person`").executeUpdate();
} );
}
@Test
public void testQuotedIdentifier() {
doInHibernate( this::sessionFactory, session -> {
@ -60,6 +68,20 @@ public class QuotedIdentifierTest extends BaseCoreFunctionalTestCase {
} );
}
@Test
public void testQuotedFunctionName() {
doInHibernate( this::sessionFactory, session -> {
TypedQuery<Tuple> query = session.createQuery(
"select `upper`(`the person`.`name`) as `The person name` " +
"from `The Person` `the person`",
Tuple.class
);
List<Tuple> resultList = query.getResultList();
assertEquals( 1, resultList.size() );
assertEquals( "CHUCK", resultList.get( 0 ).get( "The person name" ) );
} );
}
@Entity(name = "The Person")
public static class Person {