HHH-12561 - bulk_id_strategy does not work with globally_quoted_identifiers

This commit is contained in:
Vlad Mihalcea 2018-06-04 14:07:34 +03:00
parent 5e8f7347c7
commit a5e5ea48ce
3 changed files with 170 additions and 3 deletions

View File

@ -21,6 +21,7 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.hql.internal.ast.HqlSqlWalker; import org.hibernate.hql.internal.ast.HqlSqlWalker;
import org.hibernate.hql.internal.ast.tree.AbstractRestrictableStatement; import org.hibernate.hql.internal.ast.tree.AbstractRestrictableStatement;
import org.hibernate.hql.internal.ast.tree.FromElement; import org.hibernate.hql.internal.ast.tree.FromElement;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.param.ParameterSpecification; import org.hibernate.param.ParameterSpecification;
import org.hibernate.persister.entity.Queryable; import org.hibernate.persister.entity.Queryable;
@ -83,6 +84,8 @@ public abstract class AbstractIdsBulkIdHandler
position += parameterSpecification.bind( ps, queryParameters, session, position ); position += parameterSpecification.bind( ps, queryParameters, session, position );
} }
Dialect dialect = session.getFactory().getServiceRegistry().getService( JdbcServices.class ).getDialect();
ResultSet rs = session ResultSet rs = session
.getJdbcCoordinator() .getJdbcCoordinator()
.getResultSetReturn() .getResultSetReturn()
@ -90,8 +93,9 @@ public abstract class AbstractIdsBulkIdHandler
while ( rs.next() ) { while ( rs.next() ) {
Object[] result = new Object[targetedPersister.getIdentifierColumnNames().length]; Object[] result = new Object[targetedPersister.getIdentifierColumnNames().length];
for ( String columnName : targetedPersister.getIdentifierColumnNames() ) { for ( String columnName : targetedPersister.getIdentifierColumnNames() ) {
Object column = rs.getObject( columnName ); int columnIndex = rs.findColumn( StringHelper.unquote( columnName, dialect ) );
result[rs.findColumn( columnName ) - 1] = column; Object column = rs.getObject(columnIndex);
result[columnIndex - 1] = column;
} }
ids.add( result ); ids.add( result );
} }

View File

@ -16,6 +16,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.hql.internal.ast.HqlSqlWalker; import org.hibernate.hql.internal.ast.HqlSqlWalker;
import org.hibernate.hql.spi.id.AbstractIdsBulkIdHandler; import org.hibernate.hql.spi.id.AbstractIdsBulkIdHandler;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.persister.entity.Queryable; import org.hibernate.persister.entity.Queryable;
/** /**
@ -63,11 +64,16 @@ public abstract class AbstractCteValuesListBulkIdHandler extends
} }
protected String determineIdTableName(Queryable persister) { protected String determineIdTableName(Queryable persister) {
String qualifiedTableName = jdbcEnvironment.getIdentifierHelper().applyGlobalQuoting(
"HT_" + StringHelper.unquote( persister.getTableName(), jdbcEnvironment.getDialect() )
).render();
return jdbcEnvironment.getQualifiedObjectNameFormatter().format( return jdbcEnvironment.getQualifiedObjectNameFormatter().format(
new QualifiedTableName( new QualifiedTableName(
Identifier.toIdentifier( catalog ), Identifier.toIdentifier( catalog ),
Identifier.toIdentifier( schema ), Identifier.toIdentifier( schema ),
Identifier.toIdentifier( "HT_" + persister.getTableName() ) Identifier.toIdentifier( qualifiedTableName )
), ),
jdbcEnvironment.getDialect() jdbcEnvironment.getDialect()
); );

View File

@ -0,0 +1,157 @@
package org.hibernate.test.bulkid;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration;
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
import org.hibernate.hql.spi.id.inline.InlineIdsOrClauseBulkIdStrategy;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Before;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import static org.junit.Assert.assertEquals;
/**
* @author Vlad Mihalcea
*/
@TestForIssue( jiraKey = "HHH-12561" )
public class GlobalQuotedIdentifiersBulkIdTest
extends BaseEntityManagerFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] {
Person.class,
Doctor.class,
Engineer.class
};
}
@Override
protected void addConfigOptions(Map options) {
options.put( AvailableSettings.GLOBALLY_QUOTED_IDENTIFIERS, Boolean.TRUE );
options.put( AvailableSettings.HQL_BULK_ID_STRATEGY, InlineIdsOrClauseBulkIdStrategy.class.getName() );
}
@Before
public void setUp() {
doInJPA( this::entityManagerFactory, entityManager -> {
for ( int i = 0; i < entityCount(); i++ ) {
Doctor doctor = new Doctor();
doctor.setEmployed( ( i % 2 ) == 0 );
doctor.setEmployedOn( Timestamp.valueOf( "2018-06-01 00:00:00" ) );
entityManager.persist( doctor );
}
for ( int i = 0; i < entityCount(); i++ ) {
Engineer engineer = new Engineer();
engineer.setEmployed( ( i % 2 ) == 0 );
engineer.setEmployedOn( Timestamp.valueOf( "2018-06-01 00:00:00" ) );
engineer.setFellow( ( i % 2 ) == 1 );
entityManager.persist( engineer );
}
});
}
protected int entityCount() {
return 5;
}
@Test
public void testBulkUpdate() {
doInJPA( this::entityManagerFactory, entityManager -> {
int updateCount = entityManager.createQuery(
"UPDATE Person u " +
"SET u.employedOn = :date " +
"WHERE u.id IN :userIds"
)
.setParameter( "date", Timestamp.valueOf( "2018-06-03 00:00:00" ) )
.setParameter( "userIds", Arrays.asList(1L, 2L, 3L ) )
.executeUpdate();
assertEquals(3, updateCount);
});
}
@Entity(name = "Person")
@Inheritance(strategy = InheritanceType.JOINED)
public static class Person {
@Id
@GeneratedValue
private Long id;
private String name;
private boolean employed;
@Temporal( TemporalType.TIMESTAMP )
private Date employedOn;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getEmployedOn() {
return employedOn;
}
public void setEmployedOn(Date employedOn) {
this.employedOn = employedOn;
}
public boolean isEmployed() {
return employed;
}
public void setEmployed(boolean employed) {
this.employed = employed;
}
}
@Entity(name = "Doctor")
public static class Doctor extends Person {
}
@Entity(name = "Engineer")
public static class Engineer extends Person {
private boolean fellow;
public boolean isFellow() {
return fellow;
}
public void setFellow(boolean fellow) {
this.fellow = fellow;
}
}
}