HHH-16125 fix tests after adding Oracle array support

This commit is contained in:
Gavin 2023-04-29 22:01:09 +02:00 committed by Gavin King
parent 07268d6568
commit aebd601845
9 changed files with 58 additions and 168 deletions

View File

@ -17,6 +17,8 @@ import jakarta.persistence.criteria.Root;
import java.util.Arrays;
import org.hibernate.dialect.OracleDialect;
import org.hibernate.testing.orm.junit.SkipForDialect;
import org.junit.Test;
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;

View File

@ -2,6 +2,7 @@ package org.hibernate.orm.test.jpa.criteria;
import java.util.List;
import jakarta.persistence.criteria.CriteriaBuilder;
import org.hibernate.dialect.DerbyDialect;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.function.CommonFunctionFactory;
@ -42,7 +43,7 @@ public class PowerFunctionTest {
public void testIt(EntityManagerFactoryScope scope) {
scope.inTransaction(
entityManager -> {
HibernateCriteriaBuilder cb = (HibernateCriteriaBuilder) entityManager.getCriteriaBuilder();
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Double> query = cb.createQuery( Double.class );
Root<Person> root = query.from( Person.class );

View File

@ -77,11 +77,8 @@ public class ByteArrayMappingTests {
}
else {
assertThat(
jdbcMapping.getJdbcType(),
isOneOf(
jdbcTypeRegistry.getDescriptor( SqlTypes.ARRAY ),
jdbcTypeRegistry.getDescriptor( SqlTypes.SQLXML )
)
jdbcMapping.getJdbcType().getJdbcTypeCode(),
isOneOf( SqlTypes.ARRAY, SqlTypes.SQLXML, SqlTypes.VARBINARY )
);
}
}

View File

@ -73,11 +73,8 @@ public class CharacterArrayMappingTests {
}
else {
assertThat(
jdbcMapping.getJdbcType(),
isOneOf(
jdbcRegistry.getDescriptor( SqlTypes.ARRAY ),
jdbcRegistry.getDescriptor( SqlTypes.SQLXML )
)
jdbcMapping.getJdbcType().getJdbcTypeCode(),
isOneOf( SqlTypes.ARRAY, SqlTypes.SQLXML, SqlTypes.VARBINARY )
);
}
}

View File

@ -35,7 +35,6 @@ import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isOneOf;
@ -81,11 +80,8 @@ public class CharacterArrayNationalizedMappingTests {
}
else {
assertThat(
jdbcMapping.getJdbcType(),
isOneOf(
jdbcTypeRegistry.getDescriptor( SqlTypes.ARRAY ),
jdbcTypeRegistry.getDescriptor( SqlTypes.SQLXML )
)
jdbcMapping.getJdbcType().getJdbcTypeCode(),
isOneOf( SqlTypes.ARRAY, SqlTypes.SQLXML, SqlTypes.VARBINARY )
);
}
}

View File

@ -131,26 +131,27 @@ public class EnumArrayTest extends BaseNonConfigCoreFunctionalTestCase {
}
private Object nativeEnumArray(MyEnum... enums) {
// We also have to pass a Short[] for Oracle because that serializes to XML by default
if ( getDialect().supportsStandardArrays() || getDialect() instanceof OracleDialect ) {
// For native queries we must bind a Short[] instead of Byte[] even if we can use the "tinyint array" DDL type.
// This is because the JavaType we have registered for Byte[] does not implement BasicPluralJavaType.
// We can't make it implement that though, because that would be backwards incompatible,
// leading to Byte[] uses in the domain being treated as "tinyint array" or "smallint array" instead of varbinary.
// Luckily, JDBC drivers that support standard arrays are capable to coerce a Short[] to Byte[]
final Short[] array = new Short[enums.length];
for ( int i = 0; i < enums.length; i++ ) {
array[i] = enums[i] == null ? null : (short) enums[i].ordinal();
}
return array;
}
else {
final byte[] array = new byte[enums.length];
for ( int i = 0; i < enums.length; i++ ) {
array[i] = enums[i] == null ? -1 : (byte) enums[i].ordinal();
}
return array;
}
return enums;
// // We also have to pass a Short[] for Oracle because that serializes to XML by default
// if ( getDialect().supportsStandardArrays() || getDialect() instanceof OracleDialect ) {
// // For native queries we must bind a Short[] instead of Byte[] even if we can use the "tinyint array" DDL type.
// // This is because the JavaType we have registered for Byte[] does not implement BasicPluralJavaType.
// // We can't make it implement that though, because that would be backwards incompatible,
// // leading to Byte[] uses in the domain being treated as "tinyint array" or "smallint array" instead of varbinary.
// // Luckily, JDBC drivers that support standard arrays are capable to coerce a Short[] to Byte[]
// final Short[] array = new Short[enums.length];
// for ( int i = 0; i < enums.length; i++ ) {
// array[i] = enums[i] == null ? null : (short) enums[i].ordinal();
// }
// return array;
// }
// else {
// final byte[] array = new byte[enums.length];
// for ( int i = 0; i < enums.length; i++ ) {
// array[i] = enums[i] == null ? -1 : (byte) enums[i].ordinal();
// }
// return array;
// }
}
@Entity( name = "TableWithEnumArrays" )

View File

@ -43,7 +43,7 @@ import static org.junit.Assert.assertThat;
@SkipForDialect(value = SybaseASEDialect.class, comment = "Sybase or the driver are trimming trailing zeros in byte arrays")
public class EnumSetConverterTest extends BaseNonConfigCoreFunctionalTestCase {
private BindableType<Set<MyEnum>> enumSetType;
private BindableType<Set<MySpecialEnum>> enumSetType;
@Override
protected Class[] getAnnotatedClasses() {
@ -54,25 +54,25 @@ public class EnumSetConverterTest extends BaseNonConfigCoreFunctionalTestCase {
super.startUp();
inTransaction( em -> {
//noinspection unchecked
enumSetType = (BindableType<Set<MyEnum>>) em.unwrap( SessionImplementor.class )
enumSetType = (BindableType<Set<MySpecialEnum>>) em.unwrap( SessionImplementor.class )
.getFactory()
.getRuntimeMetamodels()
.getMappingMetamodel()
.getEntityDescriptor( TableWithEnumSetConverter.class )
.getPropertyType( "theSet" );
em.persist( new TableWithEnumSetConverter( 1L, new HashSet<>() ) );
em.persist( new TableWithEnumSetConverter( 2L, EnumSet.of( MyEnum.VALUE1, MyEnum.VALUE2 ) ) );
em.persist( new TableWithEnumSetConverter( 2L, EnumSet.of( MySpecialEnum.VALUE1, MySpecialEnum.VALUE2 ) ) );
em.persist( new TableWithEnumSetConverter( 3L, null ) );
QueryImplementor q;
q = em.createNamedQuery( "TableWithEnumSetConverter.Native.insert" );
q.setParameter( "id", 4L );
q.setParameter( "data", EnumSet.of( MyEnum.VALUE2, MyEnum.VALUE1, MyEnum.VALUE3 ), enumSetType );
q.setParameter( "data", EnumSet.of( MySpecialEnum.VALUE2, MySpecialEnum.VALUE1, MySpecialEnum.VALUE3 ), enumSetType );
q.executeUpdate();
q = em.createNativeQuery( "INSERT INTO table_with_enum_set_convert(id, the_set) VALUES ( :id , :data )" );
q.setParameter( "id", 5L );
q.setParameter( "data", EnumSet.of( MyEnum.VALUE2, MyEnum.VALUE1, MyEnum.VALUE3 ), enumSetType );
q.setParameter( "data", EnumSet.of( MySpecialEnum.VALUE2, MySpecialEnum.VALUE1, MySpecialEnum.VALUE3 ), enumSetType );
q.executeUpdate();
} );
}
@ -85,7 +85,7 @@ public class EnumSetConverterTest extends BaseNonConfigCoreFunctionalTestCase {
assertThat( tableRecord.getTheSet(), is( new HashSet<>() ) );
tableRecord = em.find( TableWithEnumSetConverter.class, 2L );
assertThat( tableRecord.getTheSet(), is( EnumSet.of( MyEnum.VALUE1, MyEnum.VALUE2 ) ) );
assertThat( tableRecord.getTheSet(), is( EnumSet.of( MySpecialEnum.VALUE1, MySpecialEnum.VALUE2 ) ) );
tableRecord = em.find( TableWithEnumSetConverter.class, 3L );
assertThat( tableRecord.getTheSet(), is( (Object) null ) );
@ -98,7 +98,7 @@ public class EnumSetConverterTest extends BaseNonConfigCoreFunctionalTestCase {
TypedQuery<TableWithEnumSetConverter> tq = em.createNamedQuery( "TableWithEnumSetConverter.JPQL.getById", TableWithEnumSetConverter.class );
tq.setParameter( "id", 2L );
TableWithEnumSetConverter tableRecord = tq.getSingleResult();
assertThat( tableRecord.getTheSet(), is( EnumSet.of( MyEnum.VALUE1, MyEnum.VALUE2 ) ) );
assertThat( tableRecord.getTheSet(), is( EnumSet.of( MySpecialEnum.VALUE1, MySpecialEnum.VALUE2 ) ) );
} );
}
@ -119,7 +119,7 @@ public class EnumSetConverterTest extends BaseNonConfigCoreFunctionalTestCase {
TypedQuery<TableWithEnumSetConverter> tq = em.createNamedQuery( "TableWithEnumSetConverter.Native.getById", TableWithEnumSetConverter.class );
tq.setParameter( "id", 2L );
TableWithEnumSetConverter tableRecord = tq.getSingleResult();
assertThat( tableRecord.getTheSet(), is( EnumSet.of( MyEnum.VALUE1, MyEnum.VALUE2 ) ) );
assertThat( tableRecord.getTheSet(), is( EnumSet.of( MySpecialEnum.VALUE1, MySpecialEnum.VALUE2 ) ) );
} );
}
@ -133,7 +133,7 @@ public class EnumSetConverterTest extends BaseNonConfigCoreFunctionalTestCase {
"SELECT * FROM table_with_enum_set_convert t WHERE the_set " + op + " :data",
TableWithEnumSetConverter.class
);
tq.setParameter( "data", EnumSet.of( MyEnum.VALUE1, MyEnum.VALUE2 ), enumSetType );
tq.setParameter( "data", EnumSet.of( MySpecialEnum.VALUE1, MySpecialEnum.VALUE2 ), enumSetType );
TableWithEnumSetConverter tableRecord = tq.getSingleResult();
assertThat( tableRecord.getId(), is( 2L ) );
} );
@ -160,12 +160,12 @@ public class EnumSetConverterTest extends BaseNonConfigCoreFunctionalTestCase {
@Convert(converter = MyEnumConverter.class)
@Column( name = "the_set" )
private Set<MyEnum> theSet;
private Set<MySpecialEnum> theSet;
public TableWithEnumSetConverter() {
}
public TableWithEnumSetConverter(Long id, Set<MyEnum> theSet) {
public TableWithEnumSetConverter(Long id, Set<MySpecialEnum> theSet) {
this.id = id;
this.theSet = theSet;
}
@ -178,28 +178,28 @@ public class EnumSetConverterTest extends BaseNonConfigCoreFunctionalTestCase {
this.id = id;
}
public Set<MyEnum> getTheSet() {
public Set<MySpecialEnum> getTheSet() {
return theSet;
}
public void setTheSet(Set<MyEnum> theSet) {
public void setTheSet(Set<MySpecialEnum> theSet) {
this.theSet = theSet;
}
}
public enum MyEnum {
public enum MySpecialEnum {
VALUE1, VALUE2, VALUE3
}
public static class MyEnumConverter implements AttributeConverter<MyEnum, String> {
public static class MyEnumConverter implements AttributeConverter<MySpecialEnum, String> {
@Override
public String convertToDatabaseColumn(MyEnum attribute) {
public String convertToDatabaseColumn(MySpecialEnum attribute) {
return attribute == null ? null : attribute.name();
}
@Override
public MyEnum convertToEntityAttribute(String dbData) {
return dbData == null ? null : MyEnum.valueOf( dbData );
public MySpecialEnum convertToEntityAttribute(String dbData) {
return dbData == null ? null : MySpecialEnum.valueOf( dbData );
}
}
}

View File

@ -6,102 +6,21 @@
*/
package org.hibernate.orm.test.type;
import java.sql.SQLException;
import java.sql.Statement;
import org.hibernate.boot.registry.BootstrapServiceRegistry;
import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.DatabaseVersion;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import org.hibernate.dialect.OracleDialect;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.testing.transaction.TransactionUtil;
import org.junit.Assert;
import org.junit.Test;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
@RequiresDialect( OracleDialect.class )
@TestForIssue( jiraKey = "HHH-10999")
public class OracleArrayTest extends BaseCoreFunctionalTestCase {
@Override
protected void configure(Configuration configuration) {
configuration.setProperty(
Environment.DIALECT,
MyOracleDialect.class.getName()
);
}
@Override
protected void releaseSessionFactory() {
super.releaseSessionFactory();
BootstrapServiceRegistry bootRegistry = buildBootstrapServiceRegistry();
StandardServiceRegistryImpl serviceRegistry = buildServiceRegistry(
bootRegistry,
constructAndConfigureConfiguration( bootRegistry )
);
try {
TransactionUtil.doWithJDBC(
serviceRegistry,
connection -> {
try (Statement statement = connection.createStatement()) {
connection.setAutoCommit( true );
statement.execute( "DROP TYPE INTARRAY" );
statement.execute( "DROP TYPE TEXTARRAY" );
}
}
);
}
catch (SQLException e) {
throw new RuntimeException( "Failed to drop type", e );
}
finally {
serviceRegistry.destroy();
}
}
@Override
protected void buildSessionFactory() {
BootstrapServiceRegistry bootRegistry = buildBootstrapServiceRegistry();
StandardServiceRegistryImpl serviceRegistry =
buildServiceRegistry( bootRegistry, constructAndConfigureConfiguration( bootRegistry ) );
try {
TransactionUtil.doWithJDBC(
serviceRegistry,
connection -> {
try (Statement statement = connection.createStatement()) {
connection.setAutoCommit( true );
if ( statement.executeQuery( "SELECT 1 FROM ALL_TYPES WHERE TYPE_NAME = 'INTARRAY'" ).next() ) {
statement.execute( "DROP TYPE INTARRAY" );
}
if ( statement.executeQuery( "SELECT 1 FROM ALL_TYPES WHERE TYPE_NAME = 'TEXTARRAY'" ).next() ) {
statement.execute( "DROP TYPE TEXTARRAY" );
}
statement.execute( "CREATE TYPE INTARRAY AS VARRAY(10) OF NUMBER(10,0)");
statement.execute( "CREATE TYPE TEXTARRAY AS VARRAY(10) OF VARCHAR2(255)");
}
}
);
}
catch ( SQLException e ) {
throw new RuntimeException( e );
}
finally {
serviceRegistry.destroy();
}
super.buildSessionFactory();
}
@Test
public void test() {
@ -129,10 +48,8 @@ public class OracleArrayTest extends BaseCoreFunctionalTestCase {
@Id
Integer id;
@Column(columnDefinition = "TEXTARRAY")
String[] textArray;
@Column(columnDefinition = "TEXTARRAY")
String[] textArray2;
Integer[] intArray;
@ -179,25 +96,4 @@ public class OracleArrayTest extends BaseCoreFunctionalTestCase {
}
}
public static class MyOracleDialect extends OracleDialect {
public MyOracleDialect() {
}
public MyOracleDialect(DatabaseVersion version) {
super( version );
}
public MyOracleDialect(DialectResolutionInfo info) {
super( info );
}
@Override
public String getArrayTypeName(String elementTypeName) {
if ( "number(10,0)".equals( elementTypeName ) ) {
return "INTARRAY";
}
return super.getArrayTypeName( elementTypeName );
}
}
}

View File

@ -47,7 +47,7 @@ public class StringArrayTest extends BaseNonConfigCoreFunctionalTestCase {
super.startUp();
inTransaction( em -> {
em.persist( new TableWithStringArrays( 1L, new String[]{} ) );
em.persist( new TableWithStringArrays( 2L, new String[]{ "", "test", null, "text" } ) );
em.persist( new TableWithStringArrays( 2L, new String[]{ "hello", "test", null, "text" } ) );
em.persist( new TableWithStringArrays( 3L, null ) );
Query q;
@ -71,7 +71,7 @@ public class StringArrayTest extends BaseNonConfigCoreFunctionalTestCase {
assertThat( tableRecord.getTheArray(), is( new String[]{} ) );
tableRecord = em.find( TableWithStringArrays.class, 2L );
assertThat( tableRecord.getTheArray(), is( new String[]{ "", "test", null, "text" } ) );
assertThat( tableRecord.getTheArray(), is( new String[]{ "hello", "test", null, "text" } ) );
tableRecord = em.find( TableWithStringArrays.class, 3L );
assertThat( tableRecord.getTheArray(), is( (Object) null ) );
@ -84,7 +84,7 @@ public class StringArrayTest extends BaseNonConfigCoreFunctionalTestCase {
TypedQuery<TableWithStringArrays> tq = em.createNamedQuery( "TableWithStringArrays.JPQL.getById", TableWithStringArrays.class );
tq.setParameter( "id", 2L );
TableWithStringArrays tableRecord = tq.getSingleResult();
assertThat( tableRecord.getTheArray(), is( new String[]{ "", "test", null, "text" } ) );
assertThat( tableRecord.getTheArray(), is( new String[]{ "hello", "test", null, "text" } ) );
} );
}
@ -95,7 +95,7 @@ public class StringArrayTest extends BaseNonConfigCoreFunctionalTestCase {
TypedQuery<TableWithStringArrays> tq = em.createNamedQuery( "TableWithStringArrays.Native.getById", TableWithStringArrays.class );
tq.setParameter( "id", 2L );
TableWithStringArrays tableRecord = tq.getSingleResult();
assertThat( tableRecord.getTheArray(), is( new String[]{ "", "test", null, "text" } ) );
assertThat( tableRecord.getTheArray(), is( new String[]{ "hello", "test", null, "text" } ) );
} );
}
@ -105,7 +105,7 @@ public class StringArrayTest extends BaseNonConfigCoreFunctionalTestCase {
TypedQuery<TableWithStringArrays> tq = em.createNamedQuery("TableWithStringArrays.Native.getById", TableWithStringArrays.class );
tq.setParameter( "id", 2L );
TableWithStringArrays tableRecord = tq.getSingleResult();
assertThat( tableRecord.getTheArray(), is( new String[]{ "", "test", null, "text" } ) );
assertThat( tableRecord.getTheArray(), is( new String[]{ "hello", "test", null, "text" } ) );
} );
}
@ -119,7 +119,7 @@ public class StringArrayTest extends BaseNonConfigCoreFunctionalTestCase {
"SELECT * FROM table_with_string_arrays t WHERE the_array " + op + " :data",
TableWithStringArrays.class
);
tq.setParameter( "data", new String[]{ "", "test", null, "text" } );
tq.setParameter( "data", new String[]{ "hello", "test", null, "text" } );
TableWithStringArrays tableRecord = tq.getSingleResult();
assertThat( tableRecord.getId(), is( 2L ) );
} );
@ -132,7 +132,7 @@ public class StringArrayTest extends BaseNonConfigCoreFunctionalTestCase {
Query q = em.createNamedQuery( "TableWithStringArrays.Native.getByIdUntyped" );
q.setParameter( "id", 2L );
Object[] tuple = (Object[]) q.getSingleResult();
assertThat( tuple[1], is( new String[]{ "", "test", null, "text" } ) );
assertThat( tuple[1], is( new String[]{ "hello", "test", null, "text" } ) );
} );
}