HHH-16619 don't generate table aliases beginning with _

- because Oracle hates that
- also, as suggested by @sebersole common in code, start
  generating "acronym"-based aliases
This commit is contained in:
Gavin King 2023-06-25 21:08:01 +02:00
parent cb7b364b46
commit 4bd5ebad4e
12 changed files with 103 additions and 65 deletions

View File

@ -11,6 +11,7 @@ import org.hibernate.internal.util.StringHelper;
/**
* @author Steve Ebersole
* @author Gavin King
*/
public class SqlAliasStemHelper {
/**
@ -19,13 +20,7 @@ public class SqlAliasStemHelper {
public static final SqlAliasStemHelper INSTANCE = new SqlAliasStemHelper();
public String generateStemFromEntityName(String entityName) {
final String simpleName = toSimpleEntityName( entityName );
// ideally I'd like to build the alias base from acronym form of the name. E.g.
// 'TransportationMethod` becomes 'tm', 'ShippingDestination` becomes 'sd', etc
// for now, just use the first letter
return Character.toString( Character.toLowerCase( simpleName.charAt( 0 ) ) );
return acronym( toSimpleEntityName( entityName ) );
}
private String toSimpleEntityName(String entityName) {
@ -41,7 +36,23 @@ public class SqlAliasStemHelper {
}
public String generateStemFromAttributeName(String attributeName) {
// see note above, again for now just use the first letter
return Character.toString( Character.toLowerCase( attributeName.charAt( 0 ) ) );
return acronym(attributeName);
}
private String acronym(String name) {
StringBuilder string = new StringBuilder();
char last = '\0';
for (int i = 0; i<name.length(); i++ ) {
char ch = name.charAt(i);
if ( Character.isLetter(ch) ) {
if ( string.length() == 0
|| Character.isUpperCase(ch) && !Character.isUpperCase(last) ) {
string.append( Character.toLowerCase(ch) );
}
}
last = ch;
}
return string.length() == 0 ? "z" : string.toString();
}
}

View File

@ -0,0 +1,31 @@
package org.hibernate.orm.test.associations;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
@SessionFactory
@DomainModel(annotatedClasses = {FieldWithUnderscoreTest.A.class, FieldWithUnderscoreTest.B.class})
public class FieldWithUnderscoreTest {
@Test void test(SessionFactoryScope scope) {
scope.inSession(s -> s.createSelectionQuery("from B join _a").getResultList());
scope.inSession(s -> s.createSelectionQuery("from B left join fetch _a").getResultList());
}
@Entity(name = "A")
static class A {
@Id Long _id;
}
@Entity(name = "B")
static class B {
@Id Long _id;
@ManyToOne(fetch = FetchType.LAZY) A _a;
}
}

View File

@ -46,11 +46,11 @@ class HHH15065Test {
SQLStatementInspector statementInspector = scope.getCollectingStatementInspector();
List<String> sqlQueries = statementInspector.getSqlQueries();
assertEquals( 1, sqlQueries.size() );
assertEquals( "select b1_0.id,a1_0.id,a1_0.name,c1_0.id,c1_0.name,c2_0.id,c2_0.name,e1_0.id,e1_0.name" +
assertEquals( "select b1_0.id,a1_0.id,a1_0.name,ca1_0.id,ca1_0.name,ce1_0.id,ce1_0.name,e1_0.id,e1_0.name" +
" from Book b1_0" +
" left join Person a1_0 on a1_0.id=b1_0.author_id" +
" left join Person c1_0 on c1_0.id=b1_0.coAuthor_id" +
" left join Person c2_0 on c2_0.id=b1_0.coEditor_id" +
" left join Person ca1_0 on ca1_0.id=b1_0.coAuthor_id" +
" left join Person ce1_0 on ce1_0.id=b1_0.coEditor_id" +
" left join Person e1_0 on e1_0.id=b1_0.editor_id", sqlQueries.get(0) );
}

View File

@ -56,7 +56,7 @@ public class ManyToOneJoinReuseTest {
session.createQuery( query ).getResultList();
assertEquals( 1, sqlStatementInterceptor.getSqlQueries().size() );
assertEquals(
"select b1_0.id,b2_0.isbn,b2_0.title from BookList b1_0 join book b2_0 on b2_0.isbn=b1_0.book_isbn where b2_0.isbn is not null",
"select bl1_0.id,b1_0.isbn,b1_0.title from BookList bl1_0 join book b1_0 on b1_0.isbn=bl1_0.book_isbn where b1_0.isbn is not null",
sqlStatementInterceptor.getSqlQueries().get( 0 )
);
}
@ -85,7 +85,7 @@ public class ManyToOneJoinReuseTest {
session.createQuery( query ).getResultList();
assertEquals( 1, sqlStatementInterceptor.getSqlQueries().size() );
assertEquals(
"select b1_0.id,b1_0.book_isbn from BookList b1_0 join book b2_0 on b2_0.isbn=b1_0.book_isbn where b2_0.isbn is not null and b1_0.book_isbn is not null",
"select bl1_0.id,bl1_0.book_isbn from BookList bl1_0 join book b1_0 on b1_0.isbn=bl1_0.book_isbn where b1_0.isbn is not null and bl1_0.book_isbn is not null",
sqlStatementInterceptor.getSqlQueries().get( 0 )
);
}

View File

@ -105,11 +105,7 @@ public class InheritanceQueryGroupByTest {
statementInspector.clear();
scope.inTransaction( session -> {
final MyPojo myPojo = session.createQuery(
String.format(
"select new %s(sum(e.amount), re) from MyEntity e join e.%s re group by re",
MyPojo.class.getName(),
parentProp
),
"select new MyPojo(sum(e.amount), re) from MyEntity e join e." + parentProp + " re group by re",
MyPojo.class
).getSingleResult();
assertThat( myPojo.getAmount() ).isEqualTo( 3L );

View File

@ -78,13 +78,13 @@ public class TreatDisjunctionTest {
sqlStatementInterceptor.assertExecutedCount( 1 );
assertEquals(
"select " +
"p1_0.id," +
"p1_0.DTYPE," +
"p1_0.active," +
"p1_0.openldap " +
"from PAccountDirectory p1_0 " +
"where p1_0.active=? " +
"or p1_0.openldap=?",
"pd1_0.id," +
"pd1_0.DTYPE," +
"pd1_0.active," +
"pd1_0.openldap " +
"from PAccountDirectory pd1_0 " +
"where pd1_0.active=? " +
"or pd1_0.openldap=?",
sqlStatementInterceptor.getSqlQueries().get( 0 )
);
}

View File

@ -92,7 +92,7 @@ public class DepthOneBatchTest {
"select a1_0.agency_id,a1_0.agency_txt from agency_table a1_0 where a1_0.agency_id=?"
);
assertThat( executedQueries.get( 1 ).toLowerCase() ).isEqualTo(
"select a1_0.agency_id,a1_0.agency_detail from agency_detail_table a1_0 where a1_0.agency_id=?"
"select ad1_0.agency_id,ad1_0.agency_detail from agency_detail_table ad1_0 where ad1_0.agency_id=?"
);
assertThat( executedQueries.get( 2 ).toLowerCase() ).isEqualTo(

View File

@ -88,7 +88,7 @@ public class DepthOneTest {
assertThat( executedQueries.size() ).isEqualTo( 5 );
assertThat( executedQueries.get( 0 ).toLowerCase() ).isEqualTo(
"select a1_0.agency_id,a2_0.agency_id,a2_0.agency_detail,a1_0.agency_txt from agency_table a1_0 left join agency_detail_table a2_0 on a2_0.agency_id=a1_0.agency_id where a1_0.agency_id=?"
"select a1_0.agency_id,ad1_0.agency_id,ad1_0.agency_detail,a1_0.agency_txt from agency_table a1_0 left join agency_detail_table ad1_0 on ad1_0.agency_id=a1_0.agency_id where a1_0.agency_id=?"
);
assertThat( executedQueries.get( 1 ).toLowerCase() ).isEqualTo(
@ -104,7 +104,7 @@ public class DepthOneTest {
);
assertThat( executedQueries.get( 4 ).toLowerCase() ).isEqualTo(
"select a1_0.agency_id,a1_0.agency_detail from agency_detail_table a1_0 where a1_0.agency_id=?"
"select ad1_0.agency_id,ad1_0.agency_detail from agency_detail_table ad1_0 where ad1_0.agency_id=?"
);
}
);

View File

@ -42,9 +42,9 @@ public class CompareEntityValuedPathsTest {
"1 " +
"from PERSON_TABLE p1_0 " +
"where p1_0.uk in (" +
"select c1_0.child_uk " +
"from children_uks c1_0 " +
"where p1_0.uk=c1_0.owner_uk" +
"select cu1_0.child_uk " +
"from children_uks cu1_0 " +
"where p1_0.uk=cu1_0.owner_uk" +
")",
statementInspector.getSqlQueries().get( 0 )
);
@ -110,10 +110,10 @@ public class CompareEntityValuedPathsTest {
"1 " +
"from PERSON_TABLE p1_0 " +
"where p1_0.parent_id in (" +
"select c1_1.id " +
"from children_uks c1_0 " +
"join PERSON_TABLE c1_1 on c1_1.uk=c1_0.child_uk " +
"where p1_0.uk=c1_0.owner_uk" +
"select cu1_1.id " +
"from children_uks cu1_0 " +
"join PERSON_TABLE cu1_1 on cu1_1.uk=cu1_0.child_uk " +
"where p1_0.uk=cu1_0.owner_uk" +
")",
statementInspector.getSqlQueries().get( 0 )
);
@ -134,8 +134,8 @@ public class CompareEntityValuedPathsTest {
"select " +
"1 " +
"from PERSON_TABLE p1_0 " +
"join PERSON_TABLE p2_0 on p2_0.uk=p1_0.parent_uk " +
"where p2_0.id in (" +
"join PERSON_TABLE pu1_0 on pu1_0.uk=p1_0.parent_uk " +
"where pu1_0.id in (" +
"select c1_0.children_id " +
"from PERSON_TABLE_PERSON_TABLE c1_0 " +
"where p1_0.id=c1_0.Person_id" +
@ -184,9 +184,9 @@ public class CompareEntityValuedPathsTest {
"1 " +
"from PERSON_TABLE p1_0 " +
"where p1_0.id in (" +
"select e1_0.id " +
"from PERSON_TABLE e1_0 " +
"where p1_0.uk=e1_0.supervisor_uk" +
"select eu1_0.id " +
"from PERSON_TABLE eu1_0 " +
"where p1_0.uk=eu1_0.supervisor_uk" +
")",
statementInspector.getSqlQueries().get( 0 )
);
@ -207,8 +207,8 @@ public class CompareEntityValuedPathsTest {
"select " +
"1 " +
"from PERSON_TABLE p1_0 " +
"join children_uks c1_0 on p1_0.uk=c1_0.owner_uk " +
"where c1_0.child_uk is not null",
"join children_uks cu1_0 on p1_0.uk=cu1_0.owner_uk " +
"where cu1_0.child_uk is not null",
statementInspector.getSqlQueries().get( 0 )
);
}
@ -249,9 +249,9 @@ public class CompareEntityValuedPathsTest {
"select " +
"1 " +
"from PERSON_TABLE p1_0 " +
"join (children_uks c1_0 join PERSON_TABLE c1_1 on c1_1.uk=c1_0.child_uk) on p1_0.uk=c1_0.owner_uk " +
"join PERSON_TABLE_PERSON_TABLE c2_0 on p1_0.id=c2_0.Person_id " +
"where c1_1.id=c2_0.children_id",
"join (children_uks cu1_0 join PERSON_TABLE cu1_1 on cu1_1.uk=cu1_0.child_uk) on p1_0.uk=cu1_0.owner_uk " +
"join PERSON_TABLE_PERSON_TABLE c1_0 on p1_0.id=c1_0.Person_id " +
"where cu1_1.id=c1_0.children_id",
statementInspector.getSqlQueries().get( 0 )
);
}
@ -272,8 +272,8 @@ public class CompareEntityValuedPathsTest {
"1 " +
"from PERSON_TABLE p1_0 " +
"join PERSON_TABLE_PERSON_TABLE c1_0 on p1_0.id=c1_0.Person_id " +
"join (children_uks c2_0 join PERSON_TABLE c2_1 on c2_1.uk=c2_0.child_uk) on p1_0.uk=c2_0.owner_uk " +
"where c1_0.children_id=c2_1.id",
"join (children_uks cu1_0 join PERSON_TABLE cu1_1 on cu1_1.uk=cu1_0.child_uk) on p1_0.uk=cu1_0.owner_uk " +
"where c1_0.children_id=cu1_1.id",
statementInspector.getSqlQueries().get( 0 )
);
}
@ -293,8 +293,8 @@ public class CompareEntityValuedPathsTest {
"select " +
"1 " +
"from PERSON_TABLE p1_0 " +
"join (children_uks c1_0 join PERSON_TABLE c1_1 on c1_1.uk=c1_0.child_uk) on p1_0.uk=c1_0.owner_uk " +
"where c1_1.id in (select c2_0.children_id from PERSON_TABLE_PERSON_TABLE c2_0 where p1_0.id=c2_0.Person_id)",
"join (children_uks cu1_0 join PERSON_TABLE cu1_1 on cu1_1.uk=cu1_0.child_uk) on p1_0.uk=cu1_0.owner_uk " +
"where cu1_1.id in (select c1_0.children_id from PERSON_TABLE_PERSON_TABLE c1_0 where p1_0.id=c1_0.Person_id)",
statementInspector.getSqlQueries().get( 0 )
);
}
@ -315,7 +315,7 @@ public class CompareEntityValuedPathsTest {
"1 " +
"from PERSON_TABLE p1_0 " +
"join PERSON_TABLE_PERSON_TABLE c1_0 on p1_0.id=c1_0.Person_id " +
"where c1_0.children_id in (select c2_1.id from children_uks c2_0 join PERSON_TABLE c2_1 on c2_1.uk=c2_0.child_uk where p1_0.uk=c2_0.owner_uk)",
"where c1_0.children_id in (select cu1_1.id from children_uks cu1_0 join PERSON_TABLE cu1_1 on cu1_1.uk=cu1_0.child_uk where p1_0.uk=cu1_0.owner_uk)",
statementInspector.getSqlQueries().get( 0 )
);
}

View File

@ -68,7 +68,7 @@ public class QueryTimeOutTest extends BaseNonConfigCoreFunctionalTestCase {
);
final String baseQuery;
if ( DialectContext.getDialect() instanceof OracleDialect ) {
baseQuery = "update AnEntity a1_0 set a1_0.name=";
baseQuery = "update AnEntity ae1_0 set ae1_0.name=";
}
else {
baseQuery = "update AnEntity set name=";

View File

@ -99,8 +99,8 @@ public class SameTableAliasInSubqueryWithEmbeddedTest {
query.setParameter( "countryCode", "DE" );
query.setParameter( "nested", "NESTED_2" );
assertNotNull( query.getSingleResult() );
statementInspector.assertNumberOfOccurrenceInQueryNoSpace( 0, "m1_0", 6 );
statementInspector.assertNumberOfOccurrenceInQueryNoSpace( 0, "m2_0", 5 );
statementInspector.assertNumberOfOccurrenceInQueryNoSpace( 0, "mdfe1_0", 6 );
statementInspector.assertNumberOfOccurrenceInQueryNoSpace( 0, "mdfe2_0", 5 );
} );
}
@ -118,8 +118,8 @@ public class SameTableAliasInSubqueryWithEmbeddedTest {
TypedQuery<PrimaryKey> query = session.createQuery( jpql, PrimaryKey.class );
query.setParameter( "nested", "NESTED_2" );
assertNotNull( query.getSingleResult() );
statementInspector.assertNumberOfOccurrenceInQueryNoSpace( 0, "m1_0", 4 );
statementInspector.assertNumberOfOccurrenceInQueryNoSpace( 0, "m2_0", 3 );
statementInspector.assertNumberOfOccurrenceInQueryNoSpace( 0, "mdfe1_0", 4 );
statementInspector.assertNumberOfOccurrenceInQueryNoSpace( 0, "mdfe2_0", 3 );
} );
}

View File

@ -81,9 +81,9 @@ public class SmokeTests {
assertThat( rootTableGroup.getTableGroupJoins().isEmpty(), is( true ) );
// `s` is the "alias stem" for `SimpleEntity` and as it is the first entity with that stem in
// the query the base becomes `s1`. The primary table reference is always suffixed as `_0`
assertThat( rootTableGroup.getPrimaryTableReference().getIdentificationVariable(), is( "s1_0" ) );
// `se` is the "alias stem" for `SimpleEntity` and as it is the first entity with that stem in
// the query the base becomes `se1`. The primary table reference is always suffixed as `_0`
assertThat( rootTableGroup.getPrimaryTableReference().getIdentificationVariable(), is( "se1_0" ) );
final SelectClause selectClause = sqlAst.getQuerySpec().getSelectClause();
assertThat( selectClause.getSqlSelections().size(), is( 1 ) ) ;
@ -99,7 +99,7 @@ public class SmokeTests {
assertThat(
jdbcSelectOperation.getSqlString(),
is( "select s1_0.name from mapping_simple_entity s1_0" )
is( "select se1_0.name from mapping_simple_entity se1_0" )
);
} );
}
@ -137,9 +137,9 @@ public class SmokeTests {
assertThat( rootTableGroup.getTableGroupJoins().isEmpty(), is( true ) );
// `s` is the "alias stem" for `SimpleEntity` and as it is the first entity with that stem in
// the query the base becomes `s1`. The primary table reference is always suffixed as `_0`
assertThat( rootTableGroup.getPrimaryTableReference().getIdentificationVariable(), is( "s1_0" ) );
// `se` is the "alias stem" for `SimpleEntity` and as it is the first entity with that stem in
// the query the base becomes `se1`. The primary table reference is always suffixed as `_0`
assertThat( rootTableGroup.getPrimaryTableReference().getIdentificationVariable(), is( "se1_0" ) );
final SelectClause selectClause = sqlAst.getQuerySpec().getSelectClause();
assertThat( selectClause.getSqlSelections().size(), is( 1 ) );
@ -153,7 +153,7 @@ public class SmokeTests {
final Expression selectedExpression = sqlSelection.getExpression();
assertThat( selectedExpression, instanceOf( ColumnReference.class ) );
final ColumnReference columnReference = (ColumnReference) selectedExpression;
assertThat( columnReference.getExpressionText(), is( "s1_0.gender" ) );
assertThat( columnReference.getExpressionText(), is( "se1_0.gender" ) );
final JdbcMapping selectedExpressible = selectedExpression.getExpressionType().getSingleJdbcMapping();
assertThat( selectedExpressible.getJdbcType().isInteger(), is( true ) );
@ -184,7 +184,7 @@ public class SmokeTests {
assertThat(
jdbcSelectOperation.getSqlString(),
is( "select s1_0.gender from mapping_simple_entity s1_0" )
is( "select se1_0.gender from mapping_simple_entity se1_0" )
);
}
);