diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/JavaTypesArrayTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/JavaTypesArrayTest.java
index 139ad6b78..66fb6dbbd 100644
--- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/JavaTypesArrayTest.java
+++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/JavaTypesArrayTest.java
@@ -16,7 +16,9 @@
import java.util.Set;
import java.util.UUID;
import java.util.function.Consumer;
+import java.util.function.Predicate;
+import org.hibernate.AssertionFailure;
import org.hibernate.annotations.Array;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
@@ -33,35 +35,30 @@
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
-import org.assertj.core.api.Condition;
import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.ORACLE;
-import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.POSTGRESQL;
import static org.hibernate.reactive.containers.DatabaseConfiguration.dbType;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+/**
+ * Test that we handle arrays as basic types and the @{@link Array} annotation in combination with @{@link Column}.
+ *
+ * Specifying the length doesn't seem to have any effect at the moment.
+ * We use it when creating the table with Postgres, but Postgres ignore it anyway.
+ * All the other dbs will save the array as a `varbinary` column and length is set using @{@link Column}
+ */
@Timeout(value = 10, timeUnit = MINUTES)
@DisabledFor(value = ORACLE, reason = "Vert.x does not support arrays for Oracle")
public class JavaTypesArrayTest extends BaseReactiveTest {
private static SqlStatementTracker sqlTracker;
- private final static Condition IS_PG_CREATE_TABLE_QUERY = new Condition<>(
- s -> s.toLowerCase().startsWith( "create table" ) && s.contains( "stringArrayWithArrayAnnotation varchar(255) array[5]," ),
- "generated query for PostgreSQL `create table...`"
- );
-
- private final static Condition IS_PG_CREATE_TABLE_NO_ARRAY_ANNOTATION_QUERY = new Condition<>(
- s -> s.toLowerCase().startsWith( "create table" ) && s.contains( "stringArray varchar(255) array," ),
- "generated query for PostgreSQL `create table...`"
- );
-
@Override
protected Configuration constructConfiguration() {
Configuration configuration = super.constructConfiguration();
@@ -75,7 +72,7 @@ protected void addServices(StandardServiceRegistryBuilder builder) {
}
private static boolean filterCreateTable(String s) {
- return s.toLowerCase().startsWith( "create table" );
+ return s.toLowerCase().startsWith( "create table basic " );
}
@Override
@@ -100,16 +97,12 @@ private void testField(
@Test
public void testStringArrayType(VertxTestContext context) {
Basic basic = new Basic();
- String[] dataArray = { "Hello world!", "Hello earth" };
+ String[] dataArray = {"Hello world!", "Hello earth"};
basic.stringArray = dataArray;
testField( context, basic, found -> {
assertArrayEquals( dataArray, found.stringArray );
- // PostgreSQL is the only DB that changes it's `create table...` statement to include array information
- // This test checks that the logged query is correct and contains "array[100]"
- if ( dbType() == POSTGRESQL ) {
- assertThat( sqlTracker.getLoggedQueries() ).have( IS_PG_CREATE_TABLE_NO_ARRAY_ANNOTATION_QUERY );
- }
+ validateArrayColumn( "stringArray", null, 255 );
} );
}
@@ -121,38 +114,34 @@ public void testStringArrayTypeWithArrayAnnotation(VertxTestContext context) {
testField( context, basic, found -> {
assertArrayEquals( dataArray, found.stringArrayWithArrayAnnotation );
- // PostgreSQL is the only DB that changes it's `create table...` statement to include array information
- // This test checks that the logged query is correct and contains "array[100]"
- if ( dbType() == POSTGRESQL ) {
- assertThat( sqlTracker.getLoggedQueries() ).have( IS_PG_CREATE_TABLE_QUERY );
- }
+ validateArrayColumn( "stringArrayWithArrayAnnotation", 5, null );
} );
}
@Test
public void testStringArrayTypeWithColumnAnnotation(VertxTestContext context) {
Basic basic = new Basic();
- String[] dataArray = { "Hello world!", "Hello earth" };
+ String[] dataArray = {"Hello world!", "Hello earth"};
basic.stringArrayWithColumnAnnotation = dataArray;
testField( context, basic, found -> {
assertArrayEquals( dataArray, found.stringArrayWithColumnAnnotation );
+ validateArrayColumn( "stringArrayWithColumnAnnotation", null, 200 );
} );
}
@Test
public void testStringArrayTypeWithBothAnnotations(VertxTestContext context) {
Basic basic = new Basic();
- String[] dataArray = { "Hello world!", "Hello earth" };
+ String[] dataArray = {"Hello world!", "Hello earth"};
basic.stringArrayWithBothAnnotations = dataArray;
testField( context, basic, found -> {
assertArrayEquals( dataArray, found.stringArrayWithBothAnnotations );
+ validateArrayColumn( "stringArrayWithBothAnnotations", 5, 200 );
} );
}
-
-
@Test
public void testBooleanArrayType(VertxTestContext context) {
Basic basic = new Basic();
@@ -160,6 +149,7 @@ public void testBooleanArrayType(VertxTestContext context) {
basic.booleanArray = dataArray;
testField( context, basic, found -> assertArrayEquals( dataArray, found.booleanArray ) );
+ validateArrayColumn( "booleanArray", null, null );
}
@Test
@@ -168,7 +158,10 @@ public void testPrimitiveBooleanArrayType(VertxTestContext context) {
boolean[] dataArray = {true, false, true};
basic.primitiveBooleanArray = dataArray;
- testField( context, basic, found -> assertArrayEquals( dataArray, found.primitiveBooleanArray ) );
+ testField( context, basic, found -> {
+ assertArrayEquals( dataArray, found.primitiveBooleanArray );
+ validateArrayColumn( "primitiveBooleanArray", null, null );
+ } );
}
@Test
@@ -177,7 +170,10 @@ public void testIntegerArrayType(VertxTestContext context) {
Integer[] dataArray = {null, Integer.MIN_VALUE, 2, Integer.MAX_VALUE};
basic.integerArray = dataArray;
- testField( context, basic, found -> assertArrayEquals( dataArray, found.integerArray ) );
+ testField( context, basic, found -> {
+ assertArrayEquals( dataArray, found.integerArray );
+ validateArrayColumn( "integerArray", null, null );
+ } );
}
@Test
@@ -186,7 +182,10 @@ public void testPrimitiveIntegerArrayType(VertxTestContext context) {
int[] dataArray = {1, 2, 3};
basic.primitiveIntegerArray = dataArray;
- testField( context, basic, found -> assertArrayEquals( dataArray, found.primitiveIntegerArray ) );
+ testField( context, basic, found -> {
+ assertArrayEquals( dataArray, found.primitiveIntegerArray );
+ validateArrayColumn( "primitiveIntegerArray", null, null );
+ } );
}
@Test
@@ -195,7 +194,10 @@ public void testLongArrayType(VertxTestContext context) {
Long[] dataArray = {Long.MIN_VALUE, Long.MAX_VALUE, 3L, null};
basic.longArray = dataArray;
- testField( context, basic, found -> assertArrayEquals( dataArray, found.longArray ) );
+ testField( context, basic, found -> {
+ assertArrayEquals( dataArray, found.longArray );
+ validateArrayColumn( "longArray", null, null );
+ } );
}
@Test
@@ -204,7 +206,10 @@ public void testPrimitiveLongArrayType(VertxTestContext context) {
long[] dataArray = {Long.MIN_VALUE, Long.MAX_VALUE, 3L};
basic.primitiveLongArray = dataArray;
- testField( context, basic, found -> assertArrayEquals( dataArray, found.primitiveLongArray ) );
+ testField( context, basic, found -> {
+ assertArrayEquals( dataArray, found.primitiveLongArray );
+ validateArrayColumn( "primitiveLongArray", null, null );
+ } );
}
@Test
@@ -213,7 +218,10 @@ public void testFloatArrayType(VertxTestContext context) {
Float[] dataArray = {12.562f, null, 13.562f};
basic.floatArray = dataArray;
- testField( context, basic, found -> assertArrayEquals( dataArray, found.floatArray ) );
+ testField( context, basic, found -> {
+ assertArrayEquals( dataArray, found.floatArray );
+ validateArrayColumn( "floatArray", null, null );
+ } );
}
@Test
@@ -222,7 +230,10 @@ public void testPrimitiveFloatArrayType(VertxTestContext context) {
float[] dataArray = {12.562f, 13.562f};
basic.primitiveFloatArray = dataArray;
- testField( context, basic, found -> assertArrayEquals( dataArray, found.primitiveFloatArray ) );
+ testField( context, basic, found -> {
+ assertArrayEquals( dataArray, found.primitiveFloatArray );
+ validateArrayColumn( "primitiveFloatArray", null, null );
+ } );
}
@Test
@@ -231,7 +242,10 @@ public void testDoubleArrayType(VertxTestContext context) {
Double[] dataArray = {12.562d, null, 13.562d};
basic.doubleArray = dataArray;
- testField( context, basic, found -> assertArrayEquals( dataArray, found.doubleArray ) );
+ testField( context, basic, found -> {
+ assertArrayEquals( dataArray, found.doubleArray );
+ validateArrayColumn( "doubleArray", null, null );
+ } );
}
@Test
@@ -240,7 +254,10 @@ public void testPrimitiveDoubleArrayType(VertxTestContext context) {
double[] dataArray = {12.562d, 13.562d};
basic.primitiveDoubleArray = dataArray;
- testField( context, basic, found -> assertArrayEquals( dataArray, found.primitiveDoubleArray ) );
+ testField( context, basic, found -> {
+ assertArrayEquals( dataArray, found.primitiveDoubleArray );
+ validateArrayColumn( "primitiveDoubleArray", null, null );
+ } );
}
@Test
@@ -253,7 +270,10 @@ public void testUUIDArrayType(VertxTestContext context) {
};
basic.uuidArray = dataArray;
- testField( context, basic, found -> assertArrayEquals( dataArray, found.uuidArray ) );
+ testField( context, basic, found -> {
+ assertArrayEquals( dataArray, found.uuidArray );
+ validateArrayColumn( "uuidArray", null, null );
+ } );
}
@Test
@@ -262,7 +282,10 @@ public void testEnumArrayType(VertxTestContext context) {
AnEnum[] dataArray = {AnEnum.FOURTH, AnEnum.FIRST, AnEnum.THIRD};
basic.enumArray = dataArray;
- testField( context, basic, found -> assertArrayEquals( dataArray, found.enumArray ) );
+ testField( context, basic, found -> {
+ assertArrayEquals( dataArray, found.enumArray );
+ validateArrayColumn( "enumArray", null, null );
+ } );
}
@Test
@@ -271,7 +294,10 @@ public void testShortArrayType(VertxTestContext context) {
Short[] dataArray = {512, 112, null, 0};
basic.shortArray = dataArray;
- testField( context, basic, found -> assertArrayEquals( dataArray, found.shortArray ) );
+ testField( context, basic, found -> {
+ assertArrayEquals( dataArray, found.shortArray );
+ validateArrayColumn( "shortArray", null, null );
+ } );
}
@Test
@@ -280,7 +306,10 @@ public void testPrimitiveShortArrayType(VertxTestContext context) {
short[] dataArray = {500, 32, -1};
basic.primitiveShortArray = dataArray;
- testField( context, basic, found -> assertArrayEquals( dataArray, found.primitiveShortArray ) );
+ testField( context, basic, found -> {
+ assertArrayEquals( dataArray, found.primitiveShortArray );
+ validateArrayColumn( "primitiveShortArray", null, null );
+ } );
}
@Test
@@ -294,7 +323,10 @@ public void testLocalDateArrayType(VertxTestContext context) {
};
basic.localDateArray = dataArray;
- testField( context, basic, found -> assertArrayEquals( dataArray, found.localDateArray ) );
+ testField( context, basic, found -> {
+ assertArrayEquals( dataArray, found.localDateArray );
+ validateArrayColumn( "localDateArray", null, null );
+ } );
}
@Test
@@ -303,7 +335,10 @@ public void testDateArrayType(VertxTestContext context) {
Date[] dataArray = {Calendar.getInstance().getTime(), Calendar.getInstance().getTime()};
basic.dateArray = dataArray;
- testField( context, basic, found -> assertArrayEquals( dataArray, found.dateArray ) );
+ testField( context, basic, found -> {
+ assertArrayEquals( dataArray, found.dateArray );
+ validateArrayColumn( "dateArray", null, null );
+ } );
}
@Test
@@ -317,7 +352,10 @@ public void testLocalTimeArrayType(VertxTestContext context) {
};
basic.localTimeArray = dataArray;
- testField( context, basic, found -> assertArrayEquals( dataArray, found.localTimeArray ) );
+ testField( context, basic, found -> {
+ assertArrayEquals( dataArray, found.localTimeArray );
+ validateArrayColumn( "localTimeArray", null, null );
+ } );
}
@Test
@@ -335,7 +373,10 @@ public void testLocalDateTimeArrayType(VertxTestContext context) {
};
basic.localDateTimeArray = dataArray;
- testField( context, basic, found -> assertArrayEquals( dataArray, found.localDateTimeArray ) );
+ testField( context, basic, found -> {
+ assertArrayEquals( dataArray, found.localDateTimeArray );
+ validateArrayColumn( "localDateTimeArray", null, null );
+ } );
}
@Test
@@ -344,7 +385,10 @@ public void testBigIntegerArrayType(VertxTestContext context) {
BigInteger[] dataArray = {BigInteger.TEN, BigInteger.ZERO};
basic.bigIntegerArray = dataArray;
- testField( context, basic, found -> assertArrayEquals( dataArray, found.bigIntegerArray ) );
+ testField( context, basic, found -> {
+ assertArrayEquals( dataArray, found.bigIntegerArray );
+ validateArrayColumn( "bigIntegerArray", null, 5000 );
+ } );
}
@Test
@@ -355,8 +399,9 @@ public void testBigDecimalArrayType(VertxTestContext context) {
testField( context, basic, found -> {
assertEquals( dataArray.length, found.bigDecimalArray.length );
- assertEquals( dataArray[0].compareTo( found.bigDecimalArray[0] ), 0 );
- assertEquals( dataArray[1].compareTo( found.bigDecimalArray[1] ), 0 );
+ assertEquals( 0, dataArray[0].compareTo( found.bigDecimalArray[0] ) );
+ assertEquals( 0, dataArray[1].compareTo( found.bigDecimalArray[1] ) );
+ validateArrayColumn( "bigDecimalArray", null, 5000 );
} );
}
@@ -368,11 +413,76 @@ public void testBigDecimalArrayTypeWithArrayAnnotation(VertxTestContext context)
testField( context, basic, found -> {
assertEquals( dataArray.length, found.bigDecimalArrayWithArrayAnnotation.length );
- assertEquals( dataArray[0].compareTo( found.bigDecimalArrayWithArrayAnnotation[0] ), 0 );
- assertEquals( dataArray[1].compareTo( found.bigDecimalArrayWithArrayAnnotation[1] ), 0 );
+ assertEquals( 0, dataArray[0].compareTo( found.bigDecimalArrayWithArrayAnnotation[0] ) );
+ assertEquals( 0, dataArray[1].compareTo( found.bigDecimalArrayWithArrayAnnotation[1] ) );
+ validateArrayColumn( "bigDecimalArrayWithArrayAnnotation", 5, 5000 );
} );
}
+
+ private void validateArrayColumn(String columnName, Integer arrayLength, Integer columnLength) {
+ assertThat( sqlTracker.getLoggedQueries() )
+ .allMatch( arrayColumnPredicate( columnName, arrayLength, columnLength ) );
+ }
+
+ // A predicate that checks we apply the right size to the array when required
+ private static Predicate arrayColumnPredicate(String columnName, Integer arrayLength, Integer columnLength) {
+ switch ( dbType() ) {
+ case POSTGRESQL:
+ case COCKROACHDB:
+ return postgresPredicate( columnName, arrayLength, columnLength );
+ case MYSQL:
+ case MARIA:
+ case SQLSERVER:
+ case DB2:
+ return arrayAsVarbinaryPredicate( columnName, columnLength );
+ default:
+ throw new AssertionFailure( "Unexpected database: " + dbType() );
+ }
+ }
+
+ /**
+ * For Postgres, we expect arrays to be defined as {@code array}.
+ *
+ * For example: {@code varchar(255) array[2]}
+ *
+ */
+ private static Predicate postgresPredicate(String columnName, Integer arrayLength, Integer columnLength) {
+ StringBuilder regexBuilder = new StringBuilder();
+ regexBuilder.append( ".*" );
+
+ regexBuilder.append( columnName ).append( " \\w+" );
+ // Column length only affects arrays of strings
+ if ( columnLength != null && columnName.startsWith( "string" ) ) {
+ regexBuilder.append( "\\(" ).append( columnLength ).append( "\\)" );
+ }
+ else {
+ // for some types we have a default size. For example: `varchar(255)` or `numeric(38,0)`
+ regexBuilder.append( "(\\(\\d+(,\\d+)?\\))?" );
+ }
+ regexBuilder.append( " array" );
+ if ( arrayLength != null ) {
+ regexBuilder.append( "\\[" ).append( arrayLength ).append( "\\]" );
+ }
+ regexBuilder.append( ".*" );
+ return s -> s.matches( regexBuilder.toString() );
+ }
+
+ private static Predicate arrayAsVarbinaryPredicate(String columnName, Integer columnLength) {
+ StringBuilder regexBuilder = new StringBuilder();
+ // Example of correct query definition: columnName varbinary(255)
+ regexBuilder.append( columnName ).append( " varbinary" ).append( "(" );
+ if ( columnLength != null ) {
+ regexBuilder.append( columnLength );
+ }
+ else {
+ // Default size
+ regexBuilder.append( 255 );
+ }
+ regexBuilder.append( ")" );
+ return s -> s.contains( regexBuilder.toString() );
+ }
+
@Entity(name = "Basic")
@Table(name = "Basic")
private static class Basic {
@@ -382,10 +492,10 @@ private static class Basic {
String[] stringArray;
@Array(length = 5)
String[] stringArrayWithArrayAnnotation;
- @Column(length = 255)
+ @Column(length = 200)
String[] stringArrayWithColumnAnnotation;
@Array(length = 5)
- @Column(length = 255)
+ @Column(length = 200)
String[] stringArrayWithBothAnnotations;
Boolean[] booleanArray;
boolean[] primitiveBooleanArray;