Fix test failures on nightly test pipeline

This commit is contained in:
Christian Beikov 2024-01-08 10:26:14 +01:00
parent ea7c8c6836
commit 7ec3667802
18 changed files with 378 additions and 87 deletions

View File

@ -11,6 +11,13 @@ import java.sql.DatabaseMetaData;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Types; import java.sql.Types;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.ZonedDateTime;
import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalAccessor;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
@ -21,6 +28,7 @@ import org.hibernate.LockOptions;
import org.hibernate.boot.model.FunctionContributions; import org.hibernate.boot.model.FunctionContributions;
import org.hibernate.boot.model.TypeContributions; import org.hibernate.boot.model.TypeContributions;
import org.hibernate.dialect.DB2Dialect; import org.hibernate.dialect.DB2Dialect;
import org.hibernate.dialect.DB2GetObjectExtractor;
import org.hibernate.dialect.DB2StructJdbcType; import org.hibernate.dialect.DB2StructJdbcType;
import org.hibernate.dialect.DatabaseVersion; import org.hibernate.dialect.DatabaseVersion;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
@ -82,15 +90,24 @@ import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNo
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
import org.hibernate.type.JavaObjectType; import org.hibernate.type.JavaObjectType;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType; import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
import org.hibernate.type.descriptor.jdbc.CharJdbcType; import org.hibernate.type.descriptor.jdbc.CharJdbcType;
import org.hibernate.type.descriptor.jdbc.ClobJdbcType; import org.hibernate.type.descriptor.jdbc.ClobJdbcType;
import org.hibernate.type.descriptor.jdbc.DecimalJdbcType; import org.hibernate.type.descriptor.jdbc.DecimalJdbcType;
import org.hibernate.type.descriptor.jdbc.InstantJdbcType;
import org.hibernate.type.descriptor.jdbc.LocalDateJdbcType;
import org.hibernate.type.descriptor.jdbc.LocalDateTimeJdbcType;
import org.hibernate.type.descriptor.jdbc.LocalTimeJdbcType;
import org.hibernate.type.descriptor.jdbc.ObjectNullResolvingJdbcType; import org.hibernate.type.descriptor.jdbc.ObjectNullResolvingJdbcType;
import org.hibernate.type.descriptor.jdbc.OffsetDateTimeJdbcType;
import org.hibernate.type.descriptor.jdbc.OffsetTimeJdbcType;
import org.hibernate.type.descriptor.jdbc.SmallIntJdbcType; import org.hibernate.type.descriptor.jdbc.SmallIntJdbcType;
import org.hibernate.type.descriptor.jdbc.VarbinaryJdbcType; import org.hibernate.type.descriptor.jdbc.VarbinaryJdbcType;
import org.hibernate.type.descriptor.jdbc.VarcharJdbcType; import org.hibernate.type.descriptor.jdbc.VarcharJdbcType;
import org.hibernate.type.descriptor.jdbc.XmlJdbcType; import org.hibernate.type.descriptor.jdbc.XmlJdbcType;
import org.hibernate.type.descriptor.jdbc.ZonedDateTimeJdbcType;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
import org.hibernate.type.descriptor.sql.internal.CapacityDependentDdlType; import org.hibernate.type.descriptor.sql.internal.CapacityDependentDdlType;
import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl; import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl;
@ -805,6 +822,12 @@ public class DB2LegacyDialect extends Dialect {
return "values current timestamp"; return "values current timestamp";
} }
@Override
public boolean doesRoundTemporalOnOverflow() {
// DB2 does truncation
return false;
}
@Override @Override
public boolean isCurrentTimestampSelectStringCallable() { public boolean isCurrentTimestampSelectStringCallable() {
return false; return false;
@ -877,6 +900,49 @@ public class DB2LegacyDialect extends Dialect {
.getDescriptor( Object.class ) .getDescriptor( Object.class )
) )
); );
typeContributions.contributeJdbcType( new InstantJdbcType() {
@Override
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
return new DB2GetObjectExtractor<>( javaType, this, Instant.class );
}
} );
typeContributions.contributeJdbcType( new LocalDateTimeJdbcType() {
@Override
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
return new DB2GetObjectExtractor<>( javaType, this, LocalDateTime.class );
}
} );
typeContributions.contributeJdbcType( new LocalDateJdbcType() {
@Override
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
return new DB2GetObjectExtractor<>( javaType, this, LocalDate.class );
}
} );
typeContributions.contributeJdbcType( new LocalTimeJdbcType() {
@Override
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
return new DB2GetObjectExtractor<>( javaType, this, LocalTime.class );
}
} );
typeContributions.contributeJdbcType( new OffsetDateTimeJdbcType() {
@Override
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
return new DB2GetObjectExtractor<>( javaType, this, OffsetDateTime.class );
}
} );
typeContributions.contributeJdbcType( new OffsetTimeJdbcType() {
@Override
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
return new DB2GetObjectExtractor<>( javaType, this, OffsetTime.class );
}
} );
typeContributions.contributeJdbcType( new ZonedDateTimeJdbcType() {
@Override
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
return new DB2GetObjectExtractor<>( javaType, this, ZonedDateTime.class );
}
} );
} }
@Override @Override

View File

@ -318,6 +318,11 @@ public class DerbyLegacyDialect extends Dialect {
return 52; return 52;
} }
@Override
public int getDefaultTimestampPrecision() {
return 9;
}
@Override @Override
public void initializeFunctionRegistry(FunctionContributions functionContributions) { public void initializeFunctionRegistry(FunctionContributions functionContributions) {
super.initializeFunctionRegistry(functionContributions); super.initializeFunctionRegistry(functionContributions);

View File

@ -723,6 +723,12 @@ public class HSQLLegacyDialect extends Dialect {
return "call current_timestamp"; return "call current_timestamp";
} }
@Override
public boolean doesRoundTemporalOnOverflow() {
// HSQLDB does truncation
return false;
}
/** /**
* For HSQLDB 2.0, this is a copy of the base class implementation. * For HSQLDB 2.0, this is a copy of the base class implementation.
* For HSQLDB 1.8, only READ_UNCOMMITTED is supported. * For HSQLDB 1.8, only READ_UNCOMMITTED is supported.

View File

@ -179,6 +179,12 @@ public class MariaDBLegacyDialect extends MySQLLegacyDialect {
return getVersion().isSameOrAfter( 10, 2 ); return getVersion().isSameOrAfter( 10, 2 );
} }
@Override
public boolean doesRoundTemporalOnOverflow() {
// See https://jira.mariadb.org/browse/MDEV-16991
return false;
}
@Override @Override
protected MySQLStorageEngine getDefaultMySQLStorageEngine() { protected MySQLStorageEngine getDefaultMySQLStorageEngine() {
return InnoDBStorageEngine.INSTANCE; return InnoDBStorageEngine.INSTANCE;

View File

@ -376,6 +376,11 @@ public abstract class AbstractHANADialect extends Dialect {
return super.castPattern( from, to ); return super.castPattern( from, to );
} }
@Override
public int getDefaultTimestampPrecision() {
return 7;
}
public int getDefaultDecimalPrecision() { public int getDefaultDecimalPrecision() {
//the maximum on HANA //the maximum on HANA
return 34; return 34;

View File

@ -11,6 +11,13 @@ import java.sql.DatabaseMetaData;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Types; import java.sql.Types;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.ZonedDateTime;
import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalAccessor;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
@ -74,15 +81,24 @@ import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNo
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
import org.hibernate.type.JavaObjectType; import org.hibernate.type.JavaObjectType;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType; import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
import org.hibernate.type.descriptor.jdbc.CharJdbcType; import org.hibernate.type.descriptor.jdbc.CharJdbcType;
import org.hibernate.type.descriptor.jdbc.ClobJdbcType; import org.hibernate.type.descriptor.jdbc.ClobJdbcType;
import org.hibernate.type.descriptor.jdbc.DecimalJdbcType; import org.hibernate.type.descriptor.jdbc.DecimalJdbcType;
import org.hibernate.type.descriptor.jdbc.InstantJdbcType;
import org.hibernate.type.descriptor.jdbc.LocalDateJdbcType;
import org.hibernate.type.descriptor.jdbc.LocalDateTimeJdbcType;
import org.hibernate.type.descriptor.jdbc.LocalTimeJdbcType;
import org.hibernate.type.descriptor.jdbc.ObjectNullResolvingJdbcType; import org.hibernate.type.descriptor.jdbc.ObjectNullResolvingJdbcType;
import org.hibernate.type.descriptor.jdbc.OffsetDateTimeJdbcType;
import org.hibernate.type.descriptor.jdbc.OffsetTimeJdbcType;
import org.hibernate.type.descriptor.jdbc.SmallIntJdbcType; import org.hibernate.type.descriptor.jdbc.SmallIntJdbcType;
import org.hibernate.type.descriptor.jdbc.VarbinaryJdbcType; import org.hibernate.type.descriptor.jdbc.VarbinaryJdbcType;
import org.hibernate.type.descriptor.jdbc.VarcharJdbcType; import org.hibernate.type.descriptor.jdbc.VarcharJdbcType;
import org.hibernate.type.descriptor.jdbc.XmlJdbcType; import org.hibernate.type.descriptor.jdbc.XmlJdbcType;
import org.hibernate.type.descriptor.jdbc.ZonedDateTimeJdbcType;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
import org.hibernate.type.descriptor.sql.internal.CapacityDependentDdlType; import org.hibernate.type.descriptor.sql.internal.CapacityDependentDdlType;
import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl; import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl;
@ -888,6 +904,12 @@ public class DB2Dialect extends Dialect {
return "values current timestamp"; return "values current timestamp";
} }
@Override
public boolean doesRoundTemporalOnOverflow() {
// DB2 does truncation
return false;
}
@Override @Override
public boolean isCurrentTimestampSelectStringCallable() { public boolean isCurrentTimestampSelectStringCallable() {
return false; return false;
@ -960,6 +982,49 @@ public class DB2Dialect extends Dialect {
.getDescriptor( Object.class ) .getDescriptor( Object.class )
) )
); );
typeContributions.contributeJdbcType( new InstantJdbcType() {
@Override
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
return new DB2GetObjectExtractor<>( javaType, this, Instant.class );
}
} );
typeContributions.contributeJdbcType( new LocalDateTimeJdbcType() {
@Override
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
return new DB2GetObjectExtractor<>( javaType, this, LocalDateTime.class );
}
} );
typeContributions.contributeJdbcType( new LocalDateJdbcType() {
@Override
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
return new DB2GetObjectExtractor<>( javaType, this, LocalDate.class );
}
} );
typeContributions.contributeJdbcType( new LocalTimeJdbcType() {
@Override
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
return new DB2GetObjectExtractor<>( javaType, this, LocalTime.class );
}
} );
typeContributions.contributeJdbcType( new OffsetDateTimeJdbcType() {
@Override
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
return new DB2GetObjectExtractor<>( javaType, this, OffsetDateTime.class );
}
} );
typeContributions.contributeJdbcType( new OffsetTimeJdbcType() {
@Override
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
return new DB2GetObjectExtractor<>( javaType, this, OffsetTime.class );
}
} );
typeContributions.contributeJdbcType( new ZonedDateTimeJdbcType() {
@Override
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
return new DB2GetObjectExtractor<>( javaType, this, ZonedDateTime.class );
}
} );
} }
@Override @Override

View File

@ -0,0 +1,74 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.dialect;
import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.jdbc.JavaTimeJdbcType;
import org.hibernate.type.descriptor.jdbc.internal.GetObjectExtractor;
/**
* Variant of the {@link GetObjectExtractor} that catches a {@link NullPointerException},
* because the DB2 JDBC driver runs into that exception when trying to access a {@code null} value
* with the {@code getObject(int, Class)} and {@code getObject(String, Class)} methods.
*
* @author Christian Beikov
*/
public class DB2GetObjectExtractor<T> extends GetObjectExtractor<T> {
public DB2GetObjectExtractor(
JavaType<T> javaType,
JavaTimeJdbcType jdbcType,
Class<?> baseClass) {
super( javaType, jdbcType, baseClass );
}
@Override
protected T doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
try {
return super.doExtract( rs, paramIndex, options );
}
catch (NullPointerException ex) {
final Object object = rs.getObject( paramIndex );
if ( object == null ) {
return null;
}
throw ex;
}
}
@Override
protected T doExtract(CallableStatement statement, int paramIndex, WrapperOptions options) throws SQLException {
try {
return super.doExtract( statement, paramIndex, options );
}
catch (NullPointerException ex) {
final Object object = statement.getObject( paramIndex );
if ( object == null ) {
return null;
}
throw ex;
}
}
@Override
protected T doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
try {
return super.doExtract( statement, name, options );
}
catch (NullPointerException ex) {
final Object object = statement.getObject( name );
if ( object == null ) {
return null;
}
throw ex;
}
}
}

View File

@ -307,6 +307,11 @@ public class DerbyDialect extends Dialect {
return 52; return 52;
} }
@Override
public int getDefaultTimestampPrecision() {
return 9;
}
@Override @Override
public void initializeFunctionRegistry(FunctionContributions functionContributions) { public void initializeFunctionRegistry(FunctionContributions functionContributions) {
super.initializeFunctionRegistry(functionContributions); super.initializeFunctionRegistry(functionContributions);

View File

@ -4779,6 +4779,15 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
return 6; //microseconds! return 6; //microseconds!
} }
/**
* Does this dialect round a temporal when converting from a precision higher to a lower one?
*
* @return true if rounding is applied, false if truncation is applied
*/
public boolean doesRoundTemporalOnOverflow() {
return true;
}
/** /**
* This is the default precision for a generated * This is the default precision for a generated
* column mapped to a Java {@link Float} or * column mapped to a Java {@link Float} or

View File

@ -583,6 +583,12 @@ public class HSQLDialect extends Dialect {
return "values current_timestamp"; return "values current_timestamp";
} }
@Override
public boolean doesRoundTemporalOnOverflow() {
// HSQLDB does truncation
return false;
}
@Override @Override
public boolean supportsCommentOn() { public boolean supportsCommentOn() {
return true; return true;

View File

@ -179,6 +179,12 @@ public class MariaDBDialect extends MySQLDialect {
return true; return true;
} }
@Override
public boolean doesRoundTemporalOnOverflow() {
// See https://jira.mariadb.org/browse/MDEV-16991
return false;
}
@Override @Override
protected MySQLStorageEngine getDefaultMySQLStorageEngine() { protected MySQLStorageEngine getDefaultMySQLStorageEngine() {
return InnoDBStorageEngine.INSTANCE; return InnoDBStorageEngine.INSTANCE;

View File

@ -14,6 +14,7 @@ import java.time.LocalTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder; import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField; import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.time.temporal.Temporal; import java.time.temporal.Temporal;
import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalAccessor;
import java.util.Calendar; import java.util.Calendar;
@ -447,6 +448,32 @@ public final class DateTimeUtils {
appender.appendSql( LOCAL_TIME_FORMAT.get().format( calendar.getTime() ) ); appender.appendSql( LOCAL_TIME_FORMAT.get().format( calendar.getTime() ) );
} }
/**
* Do the same conversion that databases do when they encounter a timestamp with a higher precision
* than what is supported by a column, which is to round the excess fractions.
*/
public static <T extends Temporal> T adjustToDefaultPrecision(T temporal, Dialect d) {
return adjustToPrecision( temporal, d.getDefaultTimestampPrecision(), d );
}
public static <T extends Temporal> T adjustToPrecision(T temporal, int precision, Dialect d) {
return d.doesRoundTemporalOnOverflow()
? roundToSecondPrecision( temporal, precision )
: truncateToPrecision( temporal, precision );
}
public static <T extends Temporal> T truncateToPrecision(T temporal, int precision) {
if ( precision >= 9 || !temporal.isSupported( ChronoField.NANO_OF_SECOND ) ) {
return temporal;
}
final long factor = pow10( 9 - precision );
//noinspection unchecked
return (T) temporal.with(
ChronoField.NANO_OF_SECOND,
temporal.get( ChronoField.NANO_OF_SECOND ) / factor * factor
);
}
/** /**
* Do the same conversion that databases do when they encounter a timestamp with a higher precision * Do the same conversion that databases do when they encounter a timestamp with a higher precision
* than what is supported by a column, which is to round the excess fractions. * than what is supported by a column, which is to round the excess fractions.
@ -464,6 +491,12 @@ public final class DateTimeUtils {
} }
public static <T extends Temporal> T roundToSecondPrecision(T temporal, int precision) { public static <T extends Temporal> T roundToSecondPrecision(T temporal, int precision) {
if ( precision == 0 ) {
//noinspection unchecked
return temporal.get( ChronoField.NANO_OF_SECOND ) >= 500_000_000L
? (T) temporal.plus( 1, ChronoUnit.SECONDS ).with( ChronoField.NANO_OF_SECOND, 0L )
: (T) temporal.with( ChronoField.NANO_OF_SECOND, 0L );
}
//noinspection unchecked //noinspection unchecked
return (T) temporal.with( return (T) temporal.with(
ChronoField.NANO_OF_SECOND, ChronoField.NANO_OF_SECOND,
@ -472,9 +505,9 @@ public final class DateTimeUtils {
} }
public static long roundToPrecision(int nano, int precision) { public static long roundToPrecision(int nano, int precision) {
assert precision < 9 : "Precision (scale) should be less-than 9 - " + precision; assert precision > 0 : "Can't round fractional seconds to less-than 0";
if ( precision == 0 ) { if ( precision >= 9 ) {
return 0; return nano;
} }
final int precisionMask = pow10( 9 - precision ); final int precisionMask = pow10( 9 - precision );
final int nanosToRound = nano % precisionMask; final int nanosToRound = nano % precisionMask;

View File

@ -19,6 +19,8 @@ import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.generator.EventType; import org.hibernate.generator.EventType;
import org.hibernate.generator.values.GeneratedValuesMutationDelegate; import org.hibernate.generator.values.GeneratedValuesMutationDelegate;
import org.hibernate.id.insert.AbstractReturningDelegate;
import org.hibernate.id.insert.AbstractSelectingDelegate;
import org.hibernate.id.insert.UniqueKeySelectingDelegate; import org.hibernate.id.insert.UniqueKeySelectingDelegate;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.sql.model.MutationType; import org.hibernate.sql.model.MutationType;
@ -73,7 +75,7 @@ public class MutationDelegateIdentityTest {
assertThat( entity.getName() ).isNull(); assertThat( entity.getName() ).isNull();
assertThat( inspector.getSqlQueries().get( 0 ) ).contains( "insert" ); assertThat( inspector.getSqlQueries().get( 0 ) ).contains( "insert" );
inspector.assertExecutedCount( delegate != null ? 1 : 2 ); inspector.assertExecutedCount( delegate instanceof AbstractReturningDelegate ? 1 : 2 );
} ); } );
} }
@ -97,7 +99,9 @@ public class MutationDelegateIdentityTest {
assertThat( inspector.getSqlQueries().get( 0 ) ).contains( "insert" ); assertThat( inspector.getSqlQueries().get( 0 ) ).contains( "insert" );
inspector.assertExecutedCount( inspector.assertExecutedCount(
delegate != null && delegate.supportsArbitraryValues() ? 1 : 2 delegate instanceof AbstractSelectingDelegate
? 3
: delegate != null && delegate.supportsArbitraryValues() ? 1 : 2
); );
} ); } );
} }
@ -110,7 +114,7 @@ public class MutationDelegateIdentityTest {
MutationType.UPDATE MutationType.UPDATE
); );
final SQLStatementInspector inspector = scope.getCollectingStatementInspector(); final SQLStatementInspector inspector = scope.getCollectingStatementInspector();
final Integer id = scope.fromTransaction( session -> { final Long id = scope.fromTransaction( session -> {
final IdentityAndValues entity = new IdentityAndValues(); final IdentityAndValues entity = new IdentityAndValues();
session.persist( entity ); session.persist( entity );
session.flush(); session.flush();
@ -154,7 +158,9 @@ public class MutationDelegateIdentityTest {
assertThat( inspector.getSqlQueries().get( 0 ) ).contains( "insert" ); assertThat( inspector.getSqlQueries().get( 0 ) ).contains( "insert" );
inspector.assertExecutedCount( inspector.assertExecutedCount(
delegate != null && delegate.supportsArbitraryValues() ? 1 : 2 delegate instanceof AbstractSelectingDelegate
? 3
: delegate != null && delegate.supportsArbitraryValues() ? 1 : 2
); );
final boolean shouldHaveRowId = delegate != null && delegate.supportsRowId() final boolean shouldHaveRowId = delegate != null && delegate.supportsRowId()
@ -210,7 +216,7 @@ public class MutationDelegateIdentityTest {
); );
if ( isUniqueKeyDelegate ) { if ( isUniqueKeyDelegate ) {
inspector.assertNumberOfOccurrenceInQueryNoSpace( 1, "data", 1 ); inspector.assertNumberOfOccurrenceInQueryNoSpace( 1, "data", 1 );
inspector.assertNumberOfOccurrenceInQueryNoSpace( 1, "id_column", 0 ); inspector.assertNumberOfOccurrenceInQueryNoSpace( 1, "id_column", 1 );
} }
final boolean shouldHaveRowId = delegate != null && delegate.supportsRowId() final boolean shouldHaveRowId = delegate != null && delegate.supportsRowId()
@ -238,11 +244,11 @@ public class MutationDelegateIdentityTest {
public static class IdentityOnly { public static class IdentityOnly {
@Id @Id
@GeneratedValue( strategy = GenerationType.IDENTITY ) @GeneratedValue( strategy = GenerationType.IDENTITY )
private Integer id; private Long id;
private String name; private String name;
public Integer getId() { public Long getId() {
return id; return id;
} }
@ -256,7 +262,7 @@ public class MutationDelegateIdentityTest {
public static class IdentityAndValues { public static class IdentityAndValues {
@Id @Id
@GeneratedValue( strategy = GenerationType.IDENTITY ) @GeneratedValue( strategy = GenerationType.IDENTITY )
private Integer id; private Long id;
@Generated( event = EventType.INSERT ) @Generated( event = EventType.INSERT )
@ColumnDefault( "'default_name'" ) @ColumnDefault( "'default_name'" )
@ -267,7 +273,7 @@ public class MutationDelegateIdentityTest {
private String data; private String data;
public Integer getId() { public Long getId() {
return id; return id;
} }
@ -291,7 +297,7 @@ public class MutationDelegateIdentityTest {
@Id @Id
@Column( name = "id_column" ) @Column( name = "id_column" )
@GeneratedValue( strategy = GenerationType.IDENTITY ) @GeneratedValue( strategy = GenerationType.IDENTITY )
private Integer id; private Long id;
@Generated( event = EventType.INSERT ) @Generated( event = EventType.INSERT )
@ColumnDefault( "'default_name'" ) @ColumnDefault( "'default_name'" )
@ -302,7 +308,7 @@ public class MutationDelegateIdentityTest {
private String data; private String data;
public Integer getId() { public Long getId() {
return id; return id;
} }
@ -326,7 +332,7 @@ public class MutationDelegateIdentityTest {
@Id @Id
@Column( name = "id_column" ) @Column( name = "id_column" )
@GeneratedValue( strategy = GenerationType.IDENTITY ) @GeneratedValue( strategy = GenerationType.IDENTITY )
private Integer id; private Long id;
@Generated( event = EventType.INSERT ) @Generated( event = EventType.INSERT )
@ColumnDefault( "'default_name'" ) @ColumnDefault( "'default_name'" )
@ -342,7 +348,7 @@ public class MutationDelegateIdentityTest {
this.data = data; this.data = data;
} }
public Integer getId() { public Long getId() {
return id; return id;
} }

View File

@ -14,6 +14,7 @@ import org.hibernate.annotations.SourceType;
import org.hibernate.annotations.UpdateTimestamp; import org.hibernate.annotations.UpdateTimestamp;
import org.hibernate.generator.EventType; import org.hibernate.generator.EventType;
import org.hibernate.generator.values.GeneratedValuesMutationDelegate; import org.hibernate.generator.values.GeneratedValuesMutationDelegate;
import org.hibernate.id.insert.AbstractSelectingDelegate;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.sql.model.MutationType; import org.hibernate.sql.model.MutationType;
@ -70,7 +71,9 @@ public class MutationDelegateJoinedInheritanceTest {
assertThat( inspector.getSqlQueries().get( 0 ) ).contains( "insert" ); assertThat( inspector.getSqlQueries().get( 0 ) ).contains( "insert" );
inspector.assertExecutedCount( inspector.assertExecutedCount(
delegate != null && delegate.supportsArbitraryValues() ? 1 : 2 delegate instanceof AbstractSelectingDelegate
? 3
: delegate != null && delegate.supportsArbitraryValues() ? 1 : 2
); );
} ); } );
} }
@ -89,12 +92,28 @@ public class MutationDelegateJoinedInheritanceTest {
assertThat( entity.getName() ).isEqualTo( "default_name" ); assertThat( entity.getName() ).isEqualTo( "default_name" );
assertThat( entity.getChildName() ).isEqualTo( "default_child_name" ); assertThat( entity.getChildName() ).isEqualTo( "default_child_name" );
final GeneratedValuesMutationDelegate delegate = getDelegate(
scope,
ChildEntity.class,
MutationType.INSERT
);
if ( delegate instanceof AbstractSelectingDelegate ) {
assertThat( inspector.getSqlQueries().get( 0 ) ).contains( "insert" );
assertThat( inspector.getSqlQueries().get( 2 ) ).contains( "insert" );
// Note: this is a current restriction, mutation delegates only retrieve generated values
// on the "root" table, and we expect other values to be read through a subsequent select
inspector.assertIsSelect( 3 );
inspector.assertExecutedCount( 4 );
}
else {
assertThat( inspector.getSqlQueries().get( 0 ) ).contains( "insert" ); assertThat( inspector.getSqlQueries().get( 0 ) ).contains( "insert" );
assertThat( inspector.getSqlQueries().get( 1 ) ).contains( "insert" ); assertThat( inspector.getSqlQueries().get( 1 ) ).contains( "insert" );
// Note: this is a current restriction, mutation delegates only retrieve generated values // Note: this is a current restriction, mutation delegates only retrieve generated values
// on the "root" table, and we expect other values to be read through a subsequent select // on the "root" table, and we expect other values to be read through a subsequent select
inspector.assertIsSelect( 2 ); inspector.assertIsSelect( 2 );
inspector.assertExecutedCount( 3 ); inspector.assertExecutedCount( 3 );
}
} ); } );
} }
@ -106,7 +125,7 @@ public class MutationDelegateJoinedInheritanceTest {
MutationType.UPDATE MutationType.UPDATE
); );
final SQLStatementInspector inspector = scope.getCollectingStatementInspector(); final SQLStatementInspector inspector = scope.getCollectingStatementInspector();
final Integer id = scope.fromTransaction( session -> { final Long id = scope.fromTransaction( session -> {
final BaseEntity entity = new BaseEntity(); final BaseEntity entity = new BaseEntity();
session.persist( entity ); session.persist( entity );
session.flush(); session.flush();
@ -133,7 +152,7 @@ public class MutationDelegateJoinedInheritanceTest {
@Test @Test
public void testUpdateChildEntity(SessionFactoryScope scope) { public void testUpdateChildEntity(SessionFactoryScope scope) {
final SQLStatementInspector inspector = scope.getCollectingStatementInspector(); final SQLStatementInspector inspector = scope.getCollectingStatementInspector();
final Integer id = scope.fromTransaction( session -> { final Long id = scope.fromTransaction( session -> {
final ChildEntity entity = new ChildEntity(); final ChildEntity entity = new ChildEntity();
session.persist( entity ); session.persist( entity );
session.flush(); session.flush();
@ -175,7 +194,7 @@ public class MutationDelegateJoinedInheritanceTest {
public static class BaseEntity { public static class BaseEntity {
@Id @Id
@GeneratedValue( strategy = GenerationType.IDENTITY ) @GeneratedValue( strategy = GenerationType.IDENTITY )
private Integer id; private Long id;
@Generated( event = EventType.INSERT ) @Generated( event = EventType.INSERT )
@ColumnDefault( "'default_name'" ) @ColumnDefault( "'default_name'" )
@ -187,7 +206,7 @@ public class MutationDelegateJoinedInheritanceTest {
@SuppressWarnings( "FieldCanBeLocal" ) @SuppressWarnings( "FieldCanBeLocal" )
private String data; private String data;
public Integer getId() { public Long getId() {
return id; return id;
} }

View File

@ -17,6 +17,7 @@ import org.hibernate.cfg.MappingSettings;
import org.hibernate.dialect.DB2Dialect; import org.hibernate.dialect.DB2Dialect;
import org.hibernate.dialect.DerbyDialect; import org.hibernate.dialect.DerbyDialect;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.HANADialect;
import org.hibernate.dialect.OracleDialect; import org.hibernate.dialect.OracleDialect;
import org.hibernate.dialect.SybaseDialect; import org.hibernate.dialect.SybaseDialect;
import org.hibernate.mapping.BasicValue; import org.hibernate.mapping.BasicValue;
@ -176,6 +177,7 @@ public class GlobalJavaTimeJdbcTypeTests {
@Test @Test
@SkipForDialect(dialectClass = OracleDialect.class, reason = "Oracle drivers truncate fractional seconds from the LocalTime", matchSubTypes = true) @SkipForDialect(dialectClass = OracleDialect.class, reason = "Oracle drivers truncate fractional seconds from the LocalTime", matchSubTypes = true)
@SkipForDialect(dialectClass = HANADialect.class, reason = "HANA time type does not support fractional seconds", matchSubTypes = true)
void testLocalTime(SessionFactoryScope scope) { void testLocalTime(SessionFactoryScope scope) {
final Dialect dialect = scope.getSessionFactory().getJdbcServices().getDialect(); final Dialect dialect = scope.getSessionFactory().getJdbcServices().getDialect();
final LocalTime startTime = roundToDefaultPrecision( LocalTime.now(), dialect ); final LocalTime startTime = roundToDefaultPrecision( LocalTime.now(), dialect );

View File

@ -17,6 +17,7 @@ import org.hibernate.cfg.MappingSettings;
import org.hibernate.dialect.DB2Dialect; import org.hibernate.dialect.DB2Dialect;
import org.hibernate.dialect.DerbyDialect; import org.hibernate.dialect.DerbyDialect;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.HANADialect;
import org.hibernate.dialect.OracleDialect; import org.hibernate.dialect.OracleDialect;
import org.hibernate.dialect.SybaseDialect; import org.hibernate.dialect.SybaseDialect;
import org.hibernate.mapping.BasicValue; import org.hibernate.mapping.BasicValue;
@ -176,6 +177,7 @@ public class JavaTimeJdbcTypeTests {
@Test @Test
@SkipForDialect(dialectClass = OracleDialect.class, reason = "Oracle drivers truncate fractional seconds from the LocalTime", matchSubTypes = true) @SkipForDialect(dialectClass = OracleDialect.class, reason = "Oracle drivers truncate fractional seconds from the LocalTime", matchSubTypes = true)
@SkipForDialect(dialectClass = HANADialect.class, reason = "HANA time type does not support fractional seconds", matchSubTypes = true)
void testLocalTime(SessionFactoryScope scope) { void testLocalTime(SessionFactoryScope scope) {
final Dialect dialect = scope.getSessionFactory().getJdbcServices().getDialect(); final Dialect dialect = scope.getSessionFactory().getJdbcServices().getDialect();
final LocalTime startTime = roundToDefaultPrecision( LocalTime.now(), dialect ); final LocalTime startTime = roundToDefaultPrecision( LocalTime.now(), dialect );

View File

@ -15,14 +15,12 @@ import java.time.ZonedDateTime;
import org.hibernate.annotations.FractionalSeconds; import org.hibernate.annotations.FractionalSeconds;
import org.hibernate.boot.spi.MetadataImplementor; import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.dialect.DB2Dialect; import org.hibernate.dialect.CockroachDialect;
import org.hibernate.dialect.DerbyDialect; import org.hibernate.dialect.DerbyDialect;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.H2Dialect; import org.hibernate.dialect.HANADialect;
import org.hibernate.dialect.HSQLDialect;
import org.hibernate.dialect.MariaDBDialect; import org.hibernate.dialect.MariaDBDialect;
import org.hibernate.dialect.MySQLDialect; import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.OracleDialect;
import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.dialect.SQLServerDialect; import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.dialect.SybaseDialect; import org.hibernate.dialect.SybaseDialect;
@ -97,7 +95,6 @@ public class FractionalSecondsTests {
@Test @Test
@DomainModel(annotatedClasses = TestEntity.class) @DomainModel(annotatedClasses = TestEntity.class)
@SessionFactory @SessionFactory
@SkipForDialect( dialectClass = DB2Dialect.class, reason = "Occasional mismatch in rounding versus our code" )
@SkipForDialect(dialectClass = SybaseDialect.class, reason = "Because... Sybase...", matchSubTypes = true) @SkipForDialect(dialectClass = SybaseDialect.class, reason = "Because... Sybase...", matchSubTypes = true)
void testUsage(SessionFactoryScope scope) { void testUsage(SessionFactoryScope scope) {
final Instant start = Instant.now(); final Instant start = Instant.now();
@ -111,28 +108,16 @@ public class FractionalSecondsTests {
scope.inTransaction( (session) -> { scope.inTransaction( (session) -> {
final TestEntity testEntity = session.find( TestEntity.class, 1 ); final TestEntity testEntity = session.find( TestEntity.class, 1 );
final Dialect dialect = session.getSessionFactory().getJdbcServices().getDialect(); final Dialect dialect = session.getSessionFactory().getJdbcServices().getDialect();
if ( dialect instanceof DerbyDialect assertThat( testEntity.theInstant ).isEqualTo( DateTimeUtils.adjustToDefaultPrecision( start, dialect ) );
|| dialect instanceof MariaDBDialect ) {
assertThat( testEntity.theInstant ).isEqualTo( start );
}
else {
assertThat( testEntity.theInstant ).isEqualTo( DateTimeUtils.roundToSecondPrecision( start, 6 ) );
}
} ); } );
} }
@Test @Test
@DomainModel(annotatedClasses = TestEntity0.class) @DomainModel(annotatedClasses = TestEntity0.class)
@SessionFactory @SessionFactory
@SkipForDialect( dialectClass = H2Dialect.class, reason = "Occasional mismatch in rounding versus our code" )
@SkipForDialect( dialectClass = MariaDBDialect.class, reason = "Occasional mismatch in rounding versus our code" )
@SkipForDialect( dialectClass = MySQLDialect.class, reason = "Occasional mismatch in rounding versus our code", matchSubTypes = true )
@SkipForDialect( dialectClass = OracleDialect.class, reason = "Occasional mismatch in rounding versus our code" )
@SkipForDialect( dialectClass = SQLServerDialect.class, reason = "Occasional mismatch in rounding versus our code" )
@SkipForDialect( dialectClass = PostgreSQLDialect.class, reason = "Occasional mismatch in rounding versus our code", matchSubTypes = true )
@SkipForDialect(dialectClass = DerbyDialect.class, reason = "Derby does not support sized timestamp") @SkipForDialect(dialectClass = DerbyDialect.class, reason = "Derby does not support sized timestamp")
@SkipForDialect(dialectClass = HANADialect.class, reason = "HANA does not support specifying a precision on timestamps")
@SkipForDialect(dialectClass = SybaseDialect.class, reason = "Because... Sybase...", matchSubTypes = true) @SkipForDialect(dialectClass = SybaseDialect.class, reason = "Because... Sybase...", matchSubTypes = true)
void testUsage0(SessionFactoryScope scope) { void testUsage0(SessionFactoryScope scope) {
final Instant start = Instant.now(); final Instant start = Instant.now();
@ -146,17 +131,16 @@ public class FractionalSecondsTests {
scope.inTransaction( (session) -> { scope.inTransaction( (session) -> {
final TestEntity0 testEntity = session.find( TestEntity0.class, 1 ); final TestEntity0 testEntity = session.find( TestEntity0.class, 1 );
assertThat( testEntity.theInstant ).isEqualTo( DateTimeUtils.roundToSecondPrecision( start, 0 ) ); final Dialect dialect = session.getSessionFactory().getJdbcServices().getDialect();
assertThat( testEntity.theInstant ).isEqualTo( DateTimeUtils.adjustToPrecision( start, 0, dialect ) );
} ); } );
} }
@Test @Test
@DomainModel(annotatedClasses = TestEntity3.class) @DomainModel(annotatedClasses = TestEntity3.class)
@SessionFactory @SessionFactory
@SkipForDialect( dialectClass = MariaDBDialect.class, reason = "Occasional mismatch in rounding versus our code" )
@SkipForDialect( dialectClass = HSQLDialect.class, reason = "Occasional mismatch in rounding versus our code" )
@SkipForDialect( dialectClass = DB2Dialect.class, reason = "Occasional mismatch in rounding versus our code" )
@SkipForDialect(dialectClass = DerbyDialect.class, reason = "Derby does not support sized timestamp") @SkipForDialect(dialectClass = DerbyDialect.class, reason = "Derby does not support sized timestamp")
@SkipForDialect(dialectClass = HANADialect.class, reason = "HANA does not support specifying a precision on timestamps")
@SkipForDialect(dialectClass = SybaseDialect.class, reason = "Because... Sybase...", matchSubTypes = true) @SkipForDialect(dialectClass = SybaseDialect.class, reason = "Because... Sybase...", matchSubTypes = true)
void testUsage3(SessionFactoryScope scope) { void testUsage3(SessionFactoryScope scope) {
final Instant start = Instant.now(); final Instant start = Instant.now();
@ -170,7 +154,8 @@ public class FractionalSecondsTests {
scope.inTransaction( (session) -> { scope.inTransaction( (session) -> {
final TestEntity3 testEntity = session.find( TestEntity3.class, 1 ); final TestEntity3 testEntity = session.find( TestEntity3.class, 1 );
assertThat( testEntity.theInstant ).isEqualTo( DateTimeUtils.roundToSecondPrecision( start, 3 ) ); final Dialect dialect = session.getSessionFactory().getJdbcServices().getDialect();
assertThat( testEntity.theInstant ).isEqualTo( DateTimeUtils.adjustToPrecision( start, 3, dialect ) );
} ); } );
} }
@ -181,6 +166,9 @@ public class FractionalSecondsTests {
@SkipForDialect(dialectClass = MySQLDialect.class, reason = "MySQL only supports precision <= 6", matchSubTypes = true) @SkipForDialect(dialectClass = MySQLDialect.class, reason = "MySQL only supports precision <= 6", matchSubTypes = true)
@SkipForDialect(dialectClass = SQLServerDialect.class, reason = "SQL Server only supports precision <= 6") @SkipForDialect(dialectClass = SQLServerDialect.class, reason = "SQL Server only supports precision <= 6")
@SkipForDialect(dialectClass = SybaseDialect.class, reason = "Because... Sybase...", matchSubTypes = true) @SkipForDialect(dialectClass = SybaseDialect.class, reason = "Because... Sybase...", matchSubTypes = true)
@SkipForDialect(dialectClass = PostgreSQLDialect.class, reason = "PostgreSQL only supports precision <= 6", matchSubTypes = true)
@SkipForDialect(dialectClass = CockroachDialect.class, reason = "CockroachDB only supports precision <= 6")
@SkipForDialect(dialectClass = HANADialect.class, reason = "HANA does not support specifying a precision on timestamps")
void testUsage9(SessionFactoryScope scope) { void testUsage9(SessionFactoryScope scope) {
final Instant start = Instant.now(); final Instant start = Instant.now();

View File

@ -16,14 +16,12 @@ import java.time.ZonedDateTime;
import org.hibernate.annotations.FractionalSeconds; import org.hibernate.annotations.FractionalSeconds;
import org.hibernate.annotations.JdbcTypeCode; import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.boot.spi.MetadataImplementor; import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.dialect.DB2Dialect; import org.hibernate.dialect.CockroachDialect;
import org.hibernate.dialect.DerbyDialect; import org.hibernate.dialect.DerbyDialect;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.H2Dialect; import org.hibernate.dialect.HANADialect;
import org.hibernate.dialect.HSQLDialect;
import org.hibernate.dialect.MariaDBDialect; import org.hibernate.dialect.MariaDBDialect;
import org.hibernate.dialect.MySQLDialect; import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.OracleDialect;
import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.dialect.SQLServerDialect; import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.dialect.SybaseDialect; import org.hibernate.dialect.SybaseDialect;
@ -99,7 +97,6 @@ public class JavaTimeFractionalSecondsTests {
@Test @Test
@DomainModel(annotatedClasses = TestEntity.class) @DomainModel(annotatedClasses = TestEntity.class)
@SessionFactory @SessionFactory
@SkipForDialect( dialectClass = DB2Dialect.class, reason = "Occasional mismatch in rounding versus our code" )
@SkipForDialect(dialectClass = SybaseDialect.class, reason = "Because... Sybase...", matchSubTypes = true) @SkipForDialect(dialectClass = SybaseDialect.class, reason = "Because... Sybase...", matchSubTypes = true)
void testUsage(SessionFactoryScope scope) { void testUsage(SessionFactoryScope scope) {
final Instant start = Instant.now(); final Instant start = Instant.now();
@ -113,28 +110,16 @@ public class JavaTimeFractionalSecondsTests {
scope.inTransaction( (session) -> { scope.inTransaction( (session) -> {
final TestEntity testEntity = session.find( TestEntity.class, 1 ); final TestEntity testEntity = session.find( TestEntity.class, 1 );
final Dialect dialect = session.getSessionFactory().getJdbcServices().getDialect(); final Dialect dialect = session.getSessionFactory().getJdbcServices().getDialect();
if ( dialect instanceof DerbyDialect assertThat( testEntity.theInstant ).isEqualTo( DateTimeUtils.adjustToDefaultPrecision( start, dialect ) );
|| dialect instanceof MariaDBDialect ) {
assertThat( testEntity.theInstant ).isEqualTo( start );
}
else {
assertThat( testEntity.theInstant ).isEqualTo( DateTimeUtils.roundToSecondPrecision( start, 6 ) );
}
} ); } );
} }
@Test @Test
@DomainModel(annotatedClasses = TestEntity0.class) @DomainModel(annotatedClasses = TestEntity0.class)
@SessionFactory @SessionFactory
@SkipForDialect( dialectClass = H2Dialect.class, reason = "Occasional mismatch in rounding versus our code" )
@SkipForDialect( dialectClass = MariaDBDialect.class, reason = "Occasional mismatch in rounding versus our code" )
@SkipForDialect( dialectClass = MySQLDialect.class, reason = "Occasional mismatch in rounding versus our code", matchSubTypes = true )
@SkipForDialect( dialectClass = OracleDialect.class, reason = "Occasional mismatch in rounding versus our code" )
@SkipForDialect( dialectClass = SQLServerDialect.class, reason = "Occasional mismatch in rounding versus our code" )
@SkipForDialect( dialectClass = PostgreSQLDialect.class, reason = "Occasional mismatch in rounding versus our code", matchSubTypes = true )
@SkipForDialect(dialectClass = DerbyDialect.class, reason = "Derby does not support sized timestamp") @SkipForDialect(dialectClass = DerbyDialect.class, reason = "Derby does not support sized timestamp")
@SkipForDialect(dialectClass = HANADialect.class, reason = "HANA does not support specifying a precision on timestamps")
@SkipForDialect(dialectClass = SybaseDialect.class, reason = "Because... Sybase...", matchSubTypes = true) @SkipForDialect(dialectClass = SybaseDialect.class, reason = "Because... Sybase...", matchSubTypes = true)
void testUsage0(SessionFactoryScope scope) { void testUsage0(SessionFactoryScope scope) {
final Instant start = Instant.now(); final Instant start = Instant.now();
@ -148,17 +133,16 @@ public class JavaTimeFractionalSecondsTests {
scope.inTransaction( (session) -> { scope.inTransaction( (session) -> {
final TestEntity0 testEntity = session.find( TestEntity0.class, 1 ); final TestEntity0 testEntity = session.find( TestEntity0.class, 1 );
assertThat( testEntity.theInstant ).isEqualTo( DateTimeUtils.roundToSecondPrecision( start, 0 ) ); final Dialect dialect = session.getSessionFactory().getJdbcServices().getDialect();
assertThat( testEntity.theInstant ).isEqualTo( DateTimeUtils.adjustToPrecision( start, 0, dialect ) );
} ); } );
} }
@Test @Test
@DomainModel(annotatedClasses = TestEntity3.class) @DomainModel(annotatedClasses = TestEntity3.class)
@SessionFactory @SessionFactory
@SkipForDialect( dialectClass = MariaDBDialect.class, reason = "Occasional mismatch in rounding versus our code" )
@SkipForDialect( dialectClass = HSQLDialect.class, reason = "Occasional mismatch in rounding versus our code" )
@SkipForDialect( dialectClass = DB2Dialect.class, reason = "Occasional mismatch in rounding versus our code" )
@SkipForDialect(dialectClass = DerbyDialect.class, reason = "Derby does not support sized timestamp") @SkipForDialect(dialectClass = DerbyDialect.class, reason = "Derby does not support sized timestamp")
@SkipForDialect(dialectClass = HANADialect.class, reason = "HANA does not support specifying a precision on timestamps")
@SkipForDialect(dialectClass = SybaseDialect.class, reason = "Because... Sybase...", matchSubTypes = true) @SkipForDialect(dialectClass = SybaseDialect.class, reason = "Because... Sybase...", matchSubTypes = true)
void testUsage3(SessionFactoryScope scope) { void testUsage3(SessionFactoryScope scope) {
final Instant start = Instant.now(); final Instant start = Instant.now();
@ -172,7 +156,8 @@ public class JavaTimeFractionalSecondsTests {
scope.inTransaction( (session) -> { scope.inTransaction( (session) -> {
final TestEntity3 testEntity = session.find( TestEntity3.class, 1 ); final TestEntity3 testEntity = session.find( TestEntity3.class, 1 );
assertThat( testEntity.theInstant ).isEqualTo( DateTimeUtils.roundToSecondPrecision( start, 3 ) ); final Dialect dialect = session.getSessionFactory().getJdbcServices().getDialect();
assertThat( testEntity.theInstant ).isEqualTo( DateTimeUtils.adjustToPrecision( start, 3, dialect ) );
} ); } );
} }
@ -183,6 +168,9 @@ public class JavaTimeFractionalSecondsTests {
@SkipForDialect(dialectClass = MySQLDialect.class, reason = "MySQL only supports precision <= 6", matchSubTypes = true) @SkipForDialect(dialectClass = MySQLDialect.class, reason = "MySQL only supports precision <= 6", matchSubTypes = true)
@SkipForDialect(dialectClass = SQLServerDialect.class, reason = "SQL Server only supports precision <= 6") @SkipForDialect(dialectClass = SQLServerDialect.class, reason = "SQL Server only supports precision <= 6")
@SkipForDialect(dialectClass = SybaseDialect.class, reason = "Because... Sybase...", matchSubTypes = true) @SkipForDialect(dialectClass = SybaseDialect.class, reason = "Because... Sybase...", matchSubTypes = true)
@SkipForDialect(dialectClass = PostgreSQLDialect.class, reason = "PostgreSQL only supports precision <= 6", matchSubTypes = true)
@SkipForDialect(dialectClass = CockroachDialect.class, reason = "CockroachDB only supports precision <= 6")
@SkipForDialect(dialectClass = HANADialect.class, reason = "HANA does not support specifying a precision on timestamps")
void testUsage9(SessionFactoryScope scope) { void testUsage9(SessionFactoryScope scope) {
final Instant start = Instant.now(); final Instant start = Instant.now();