HHH-12492 Qualify references to columns from the target table in subqueries in DELETE/UPDATE queries

Don't try to duplicate the logic from
org.hibernate.hql.internal.ast.tree.FromElementType#toColumns(java.lang.String, java.lang.String, boolean, boolean)
in other classes, it's complex enough and already seems to handle all
the cases we might encounter.

In this specific case, we want the table name to be used to qualify
column names, because the target table doesn't have any alias (it's not
supported by every version of every RDBMS), and not qualifying columns
at all may lead to a confusing statement, in particular if tables
referenced in the subquery contain columns with the same name.
Since we use aliases for every other table in the query, referencing the
table should not lead to any conflict.
This commit is contained in:
Yoann Rodière 2018-07-18 18:39:39 +02:00 committed by Guillaume Smet
parent 6cf91c832c
commit b8b7a0f19b
3 changed files with 4 additions and 16 deletions

View File

@ -341,12 +341,10 @@ public class FromElement extends HqlSqlWalkerNode implements DisplayableNode, Pa
final String propertyName = getIdentifierPropertyName(); final String propertyName = getIdentifierPropertyName();
if ( getWalker().getStatementType() == HqlSqlTokenTypes.SELECT ) { return toColumns(
return getPropertyMapping( propertyName ).toColumns( table, propertyName ); table, propertyName,
} getWalker().getStatementType() == HqlSqlTokenTypes.SELECT
else { );
return getPropertyMapping( propertyName ).toColumns( propertyName );
}
} }
public void setCollectionJoin(boolean collectionJoin) { public void setCollectionJoin(boolean collectionJoin) {

View File

@ -197,14 +197,6 @@ public class IdentNode extends FromReferenceNode implements SelectExpression {
String[] columnExpressions = element.getIdentityColumns(); String[] columnExpressions = element.getIdentityColumns();
// determine whether to apply qualification (table alias) to the column(s)...
if ( ! isFromElementUpdateOrDeleteRoot( element ) ) {
if ( StringHelper.isNotEmpty( element.getTableAlias() ) ) {
// apparently we also need to check that they are not already qualified. Ugh!
columnExpressions = StringHelper.qualifyIfNot( element.getTableAlias(), columnExpressions );
}
}
final Dialect dialect = getWalker().getSessionFactoryHelper().getFactory().getDialect(); final Dialect dialect = getWalker().getSessionFactoryHelper().getFactory().getDialect();
final boolean isInCount = getWalker().isInCount(); final boolean isInCount = getWalker().isInCount();
final boolean isInDistinctCount = isInCount && getWalker().isInCountDistinct(); final boolean isInDistinctCount = isInCount && getWalker().isInCountDistinct();

View File

@ -10,7 +10,6 @@ import javax.persistence.criteria.CriteriaQuery;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.FailureExpected;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
@ -26,7 +25,6 @@ public class DeleteQuerySubqueryReferencingTargetPropertyTest extends BaseEntity
} }
@Test @Test
@FailureExpected(jiraKey = "HHH-12492")
public void testSubQueryReferencingTargetProperty() { public void testSubQueryReferencingTargetProperty() {
// prepare // prepare
doInJPA( this::entityManagerFactory, entityManager -> { doInJPA( this::entityManagerFactory, entityManager -> {