HHH-15115 Fix PostgreSQL SqmMultiTableMutationStrategy

This commit is contained in:
Andrea Boriero 2022-03-11 18:33:28 +01:00 committed by Christian Beikov
parent 6169a60ecd
commit cd78676608
5 changed files with 255 additions and 15 deletions

View File

@ -11,6 +11,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import org.hibernate.boot.model.naming.Identifier; import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.mapping.PluralAttributeMapping;
@ -182,18 +183,20 @@ public class CteDeleteHandler extends AbstractCteMutationHandler implements Dele
@Override @Override
protected String getCteTableName(String tableExpression) { protected String getCteTableName(String tableExpression) {
final Dialect dialect = getSessionFactory().getJdbcServices().getDialect();
if ( Identifier.isQuoted( tableExpression ) ) { if ( Identifier.isQuoted( tableExpression ) ) {
tableExpression = tableExpression.substring( 1, tableExpression.length() - 1 ); tableExpression = tableExpression.substring( 1, tableExpression.length() - 1 );
return DELETE_RESULT_TABLE_NAME_PREFIX + tableExpression;
} }
return DELETE_RESULT_TABLE_NAME_PREFIX + tableExpression; return Identifier.toIdentifier( DELETE_RESULT_TABLE_NAME_PREFIX + tableExpression ).render( dialect );
} }
protected String getCteTableName(PluralAttributeMapping pluralAttribute) { protected String getCteTableName(PluralAttributeMapping pluralAttribute) {
final Dialect dialect = getSessionFactory().getJdbcServices().getDialect();
final String hibernateEntityName = pluralAttribute.findContainingEntityMapping().getEntityName(); final String hibernateEntityName = pluralAttribute.findContainingEntityMapping().getEntityName();
final String jpaEntityName = getSessionFactory().getJpaMetamodel().entity( hibernateEntityName ).getName(); final String jpaEntityName = getSessionFactory().getJpaMetamodel().entity( hibernateEntityName ).getName();
return DELETE_RESULT_TABLE_NAME_PREFIX + jpaEntityName + "_" + pluralAttribute.getRootPathName().substring( return Identifier.toIdentifier(
hibernateEntityName.length() + 1 DELETE_RESULT_TABLE_NAME_PREFIX + jpaEntityName + "_" +
); pluralAttribute.getRootPathName().substring( hibernateEntityName.length() + 1 )
).render( dialect );
} }
} }

View File

@ -17,6 +17,7 @@ import java.util.Map;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import org.hibernate.boot.model.naming.Identifier; import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.temptable.TemporaryTable; import org.hibernate.dialect.temptable.TemporaryTable;
import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -1151,14 +1152,11 @@ public class CteInsertHandler implements InsertHandler {
} }
protected String getCteTableName(String tableExpression, String subPrefix) { protected String getCteTableName(String tableExpression, String subPrefix) {
final Dialect dialect = sessionFactory.getJdbcServices().getDialect();
if ( Identifier.isQuoted( tableExpression ) ) { if ( Identifier.isQuoted( tableExpression ) ) {
tableExpression = unquote( tableExpression ); tableExpression = tableExpression.substring( 1, tableExpression.length() - 1 );
return DML_RESULT_TABLE_NAME_PREFIX + subPrefix + tableExpression;
} }
return DML_RESULT_TABLE_NAME_PREFIX + subPrefix + tableExpression; return Identifier.toIdentifier( DML_RESULT_TABLE_NAME_PREFIX + subPrefix + tableExpression ).render( dialect );
} }
private String unquote(String tableExpression) {
return tableExpression.substring( 1, tableExpression.length() - 1 );
}
} }

View File

@ -12,6 +12,7 @@ import java.util.Map;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import org.hibernate.boot.model.naming.Identifier; import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
@ -324,19 +325,19 @@ public class CteUpdateHandler extends AbstractCteMutationHandler implements Upda
@Override @Override
protected String getCteTableName(String tableExpression) { protected String getCteTableName(String tableExpression) {
final Dialect dialect = getSessionFactory().getJdbcServices().getDialect();
if ( Identifier.isQuoted( tableExpression ) ) { if ( Identifier.isQuoted( tableExpression ) ) {
tableExpression = tableExpression.substring( 1, tableExpression.length() - 1 ); tableExpression = tableExpression.substring( 1, tableExpression.length() - 1 );
return UPDATE_RESULT_TABLE_NAME_PREFIX + tableExpression;
} }
return UPDATE_RESULT_TABLE_NAME_PREFIX + tableExpression; return Identifier.toIdentifier( UPDATE_RESULT_TABLE_NAME_PREFIX + tableExpression ).render( dialect );
} }
protected String getInsertCteTableName(String tableExpression) { protected String getInsertCteTableName(String tableExpression) {
final Dialect dialect = getSessionFactory().getJdbcServices().getDialect();
if ( Identifier.isQuoted( tableExpression ) ) { if ( Identifier.isQuoted( tableExpression ) ) {
tableExpression = tableExpression.substring( 1, tableExpression.length() - 1 ); tableExpression = tableExpression.substring( 1, tableExpression.length() - 1 );
return INSERT_RESULT_TABLE_NAME_PREFIX + tableExpression;
} }
return INSERT_RESULT_TABLE_NAME_PREFIX + tableExpression; return Identifier.toIdentifier( INSERT_RESULT_TABLE_NAME_PREFIX + tableExpression ).render( dialect );
} }
private Expression asExpression(SelectClause selectClause) { private Expression asExpression(SelectClause selectClause) {

View File

@ -0,0 +1,114 @@
package org.hibernate.orm.test.inheritance;
import org.hibernate.testing.TestForIssue;
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.BeforeEach;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Inheritance;
import jakarta.persistence.InheritanceType;
@DomainModel(
annotatedClasses = {
JoinedInheritanceDeletionTest.Person.class,
JoinedInheritanceDeletionTest.Employee.class,
JoinedInheritanceDeletionTest.Customer.class
}
)
@SessionFactory
@TestForIssue(jiraKey = "HHH-15115")
public class JoinedInheritanceDeletionTest {
@BeforeEach
public void setUp(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
Person person = new Person( 1, "Bob" );
Employee employee = new Employee( 2, "Chris", "Software Engineer" );
Customer customer = new Customer( 3, "Miriam", "" );
session.save( person );
session.save( employee );
session.save( customer );
}
);
}
@Test
public void testDelete(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.createQuery( "delete from Person" ).executeUpdate();
}
);
}
@Entity(name = "Person")
@Inheritance(strategy = InheritanceType.JOINED)
public static class Person {
@Id
private Integer id;
private String name;
public Person() {
}
public Person(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
}
@Entity(name = "Customer")
public static class Customer extends Person {
private String comments;
public Customer() {
}
public Customer(Integer id, String name, String comments) {
super( id, name );
this.comments = comments;
}
public String getComments() {
return comments;
}
}
@Entity(name = "Employee")
public static class Employee extends Person {
private String title;
public Employee() {
}
public Employee(Integer id, String name, String title) {
super( id, name );
this.title = title;
}
public String getTitle() {
return title;
}
}
}

View File

@ -0,0 +1,124 @@
package org.hibernate.orm.test.inheritance;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.RequiresDialect;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Inheritance;
import jakarta.persistence.InheritanceType;
@RequiresDialect(PostgreSQLDialect.class)
@DomainModel(
annotatedClasses = {
JoinedInheritanceWithDefaultSchemaDeletionTest.Person.class,
JoinedInheritanceWithDefaultSchemaDeletionTest.Employee.class,
JoinedInheritanceWithDefaultSchemaDeletionTest.Customer.class
}
)
@SessionFactory
@ServiceRegistry(
settings = @Setting( name = AvailableSettings.DEFAULT_SCHEMA,value = "public")
)
@TestForIssue(jiraKey = "HHH-15115")
public class JoinedInheritanceWithDefaultSchemaDeletionTest {
@BeforeEach
public void setUp(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
Person person = new Person( 1, "Bob" );
Employee employee = new Employee( 2, "Chris", "Software Engineer" );
Customer customer = new Customer( 3, "Miriam", "" );
session.save( person );
session.save( employee );
session.save( customer );
}
);
}
@Test
public void testDelete(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.createQuery( "delete from Person" ).executeUpdate();
}
);
}
@Entity(name = "Person")
@Inheritance(strategy = InheritanceType.JOINED)
public static class Person {
@Id
private Integer id;
private String name;
public Person() {
}
public Person(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
}
@Entity(name = "Customer")
public static class Customer extends Person {
private String comments;
public Customer() {
}
public Customer(Integer id, String name, String comments) {
super( id, name );
this.comments = comments;
}
public String getComments() {
return comments;
}
}
@Entity(name = "Employee")
public static class Employee extends Person {
private String title;
public Employee() {
}
public Employee(Integer id, String name, String title) {
super( id, name );
this.title = title;
}
public String getTitle() {
return title;
}
}
}