HHH-18343 fix Altibase integration test failures since Hibernate 6.5.2

This commit is contained in:
Geoffrey Park 2024-07-08 16:07:49 +09:00 committed by Christian Beikov
parent b48d0cf0f3
commit 228bd7958f
10 changed files with 92 additions and 30 deletions

View File

@ -6,18 +6,26 @@
*/
package org.hibernate.community.dialect;
import java.sql.*;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.sql.Types;
import java.time.temporal.TemporalAccessor;
import java.util.Date;
import java.util.TimeZone;
import jakarta.persistence.TemporalType;
import org.hibernate.boot.model.FunctionContributions;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.community.dialect.sequence.*;
import org.hibernate.dialect.*;
import org.hibernate.dialect.function.CommonFunctionFactory;
import org.hibernate.community.dialect.pagination.AltibaseLimitHandler;
import org.hibernate.community.dialect.sequence.AltibaseSequenceSupport;
import org.hibernate.community.dialect.sequence.SequenceInformationExtractorAltibaseDatabaseImpl;
import org.hibernate.dialect.BooleanDecoder;
import org.hibernate.dialect.DatabaseVersion;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.DmlTargetColumnQualifierSupport;
import org.hibernate.dialect.NationalizationSupport;
import org.hibernate.dialect.NullOrdering;
import org.hibernate.dialect.OracleDialect;
import org.hibernate.dialect.function.CommonFunctionFactory;
import org.hibernate.dialect.function.OracleTruncFunction;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.sequence.SequenceSupport;
@ -30,8 +38,12 @@ import org.hibernate.exception.ConstraintViolationException;
import org.hibernate.exception.LockTimeoutException;
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
import org.hibernate.internal.util.JdbcExceptionHelper;
import org.hibernate.query.sqm.*;
import org.hibernate.query.sqm.CastType;
import org.hibernate.query.sqm.IntervalType;
import org.hibernate.query.sqm.TemporalUnit;
import org.hibernate.query.sqm.TrimSpec;
import org.hibernate.query.sqm.produce.function.FunctionParameterType;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
@ -46,7 +58,22 @@ import org.hibernate.type.descriptor.sql.internal.CapacityDependentDdlType;
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
import org.hibernate.type.spi.TypeConfiguration;
import static org.hibernate.type.SqlTypes.*;
import jakarta.persistence.TemporalType;
import static org.hibernate.type.SqlTypes.BINARY;
import static org.hibernate.type.SqlTypes.BIT;
import static org.hibernate.type.SqlTypes.BOOLEAN;
import static org.hibernate.type.SqlTypes.DOUBLE;
import static org.hibernate.type.SqlTypes.FLOAT;
import static org.hibernate.type.SqlTypes.LONGVARBINARY;
import static org.hibernate.type.SqlTypes.LONGVARCHAR;
import static org.hibernate.type.SqlTypes.NCLOB;
import static org.hibernate.type.SqlTypes.TIME;
import static org.hibernate.type.SqlTypes.TIMESTAMP;
import static org.hibernate.type.SqlTypes.TIMESTAMP_WITH_TIMEZONE;
import static org.hibernate.type.SqlTypes.TIME_WITH_TIMEZONE;
import static org.hibernate.type.SqlTypes.TINYINT;
import static org.hibernate.type.SqlTypes.VARBINARY;
import static org.hibernate.type.descriptor.DateTimeUtils.JDBC_ESCAPE_END;
import static org.hibernate.type.descriptor.DateTimeUtils.JDBC_ESCAPE_START_TIMESTAMP;
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithMicros;
@ -217,6 +244,20 @@ public class AltibaseDialect extends Dialect {
new OracleTruncFunction( functionContributions.getTypeConfiguration() )
);
functionContributions.getFunctionRegistry().registerAlternateKey( "truncate", "trunc" );
// Use `numor`, `numand`, and `numxor` because bitwise operators work only in binary columns in Altibase.
functionContributions.getFunctionRegistry().patternDescriptorBuilder( "bitand", "numand(?1,?2)" )
.setExactArgumentCount( 2 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register();
functionContributions.getFunctionRegistry().patternDescriptorBuilder( "bitor", "numor(?1,?2)" )
.setExactArgumentCount( 2 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register();
functionContributions.getFunctionRegistry().patternDescriptorBuilder( "bitxor", "numxor(?1,?2)" )
.setExactArgumentCount( 2 )
.setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE )
.register();
}
@Override
@ -236,12 +277,13 @@ public class AltibaseDialect extends Dialect {
@Override
public String currentLocalTime() {
return currentTimestamp();
return currentLocalTimestamp();
}
@Override
public String currentLocalTimestamp() {
return currentTimestamp();
// Drop microseconds, because sysdate comes with microseconds.
return "trunc(sysdate,'second')";
}
@Override
@ -260,9 +302,13 @@ public class AltibaseDialect extends Dialect {
};
}
/**
* In Altibase, `timestampadd` and `datediff` with microseconds have limitations,
* so use seconds as the native precision.
*/
@Override
public long getFractionalSecondPrecisionInNanos() {
return 1_000; //microseconds
return 1_000_000_000; //seconds
}
/**
@ -305,7 +351,7 @@ public class AltibaseDialect extends Dialect {
case NANOSECOND:
return "timestampadd(MICROSECOND,(?2)/1e3,?3)";
case NATIVE:
return "timestampadd(MICROSECOND, ?2, ?3)";
return "timestampadd(SECOND, ?2, ?3)";
default:
return "timestampadd(?1, ?2, ?3)";
}
@ -315,11 +361,10 @@ public class AltibaseDialect extends Dialect {
public String timestampdiffPattern(TemporalUnit unit, TemporalType fromTemporalType, TemporalType toTemporalType) {
switch (unit) {
case SECOND:
case NATIVE:
return "datediff(?2, ?3, 'SECOND')";
case NANOSECOND:
return "datediff(?2, ?3, 'MICROSECOND')*1e3";
case NATIVE:
return "datediff(?2, ?3, 'MICROSECOND')";
default:
return "datediff(?2, ?3, '?1')";
}

View File

@ -19,6 +19,7 @@ import org.hibernate.sql.ast.SqlAstJoinType;
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
import org.hibernate.sql.ast.tree.Statement;
import org.hibernate.sql.ast.tree.delete.DeleteStatement;
import org.hibernate.sql.ast.tree.expression.BinaryArithmeticExpression;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.FunctionExpression;
import org.hibernate.sql.ast.tree.expression.Literal;
@ -207,6 +208,14 @@ public class AltibaseSqlAstTranslator<T extends JdbcOperation> extends AbstractS
}
}
@Override
public void visitBinaryArithmeticExpression(BinaryArithmeticExpression arithmeticExpression) {
if ( isIntegerDivisionEmulationRequired( arithmeticExpression ) ) {
appendSql( "floor" );
}
super.visitBinaryArithmeticExpression(arithmeticExpression);
}
@Override
public void visitQueryPartTableReference(QueryPartTableReference tableReference) {
emulateQueryPartTableReferenceColumnAliasing( tableReference );

View File

@ -11,7 +11,9 @@ import jakarta.persistence.MapsId;
import jakarta.persistence.OneToMany;
import jakarta.persistence.PrimaryKeyJoinColumn;
import jakarta.persistence.Table;
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
@ -23,6 +25,7 @@ import static jakarta.persistence.CascadeType.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
@SessionFactory
@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class)
@DomainModel(annotatedClasses ={MapsIdClassTest.User.class, MapsIdClassTest.UserAuthority.class})
public class MapsIdClassTest {

View File

@ -11,11 +11,11 @@ import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced;
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.JiraKey;
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
@ -50,7 +50,7 @@ import org.junit.jupiter.api.Test;
)
@SessionFactory(applyCollectionsInDefaultFetchGroup = false)
@BytecodeEnhanced
@RequiresDialectFeature(DialectChecks.SupportsIdentityColumns.class)
@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class)
public class DirtyTrackingNotInDefaultFetchGroupPersistTest {
@Test

View File

@ -25,16 +25,14 @@ import jakarta.persistence.OrderColumn;
import jakarta.persistence.Temporal;
import jakarta.persistence.TemporalType;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced;
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.JiraKey;
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
@ -50,7 +48,7 @@ import org.junit.jupiter.api.Test;
)
@SessionFactory
@BytecodeEnhanced
@RequiresDialectFeature(DialectChecks.SupportsIdentityColumns.class)
@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class)
public class DirtyTrackingPersistTest {
@Test

View File

@ -26,9 +26,9 @@ import org.hibernate.cfg.Environment;
import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext;
import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
@ -53,7 +53,7 @@ import org.junit.jupiter.api.Test;
@SessionFactory
@BytecodeEnhanced
@CustomEnhancementContext({ DirtyCheckEnhancementContext.class })
@RequiresDialectFeature(DialectChecks.SupportsIdentityColumns.class)
@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class)
public class DirtyCheckPrivateUnMappedCollectionTest {
@BeforeAll

View File

@ -18,12 +18,12 @@ import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Environment;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext;
import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced;
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.JiraKey;
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
@ -55,7 +55,7 @@ import static org.junit.jupiter.api.Assumptions.assumeFalse;
@SessionFactory
@BytecodeEnhanced
@CustomEnhancementContext({ DirtyCheckEnhancementContext.class, NoDirtyCheckEnhancementContext.class })
@RequiresDialectFeature(DialectChecks.SupportsIdentityColumns.class)
@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class)
public class LoadAndUpdateEntitiesWithCollectionsTest {
@BeforeAll

View File

@ -21,12 +21,12 @@ import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Environment;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext;
import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced;
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.JiraKey;
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
@ -58,7 +58,7 @@ import org.junit.jupiter.api.Test;
@SessionFactory
@BytecodeEnhanced
@CustomEnhancementContext({ NoDirtyCheckEnhancementContext.class, DirtyCheckEnhancementContext.class })
@RequiresDialectFeature(DialectChecks.SupportsIdentityColumns.class)
@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class)
public class DynamicUpdateAndCollectionsTest {
@BeforeAll

View File

@ -1301,6 +1301,8 @@ public class FunctionTests {
// really this could and should be made work on these dialects
@SkipForDialect(dialectClass = DerbyDialect.class)
@SkipForDialect(dialectClass = SybaseDialect.class, matchSubTypes = true)
@SkipForDialect(dialectClass = AltibaseDialect.class,
reason = "Altibase timestampadd does not support seconds with fractional part")
public void testAddSecondsWithFractionalPart(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
@ -1711,6 +1713,8 @@ public class FunctionTests {
reason = "numeric overflow")
@SkipForDialect( dialectClass = TiDBDialect.class,
reason = "Bug in the TiDB timestampadd function (https://github.com/pingcap/tidb/issues/41052)")
@SkipForDialect( dialectClass = AltibaseDialect.class,
reason = "exceeds timestampadd limit in Altibase")
public void testDurationArithmeticOverflowing(SessionFactoryScope scope) {
scope.inTransaction(
session -> {

View File

@ -7,7 +7,9 @@ import jakarta.persistence.Id;
import jakarta.persistence.Version;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
@ -20,6 +22,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
@SessionFactory
@DomainModel(annotatedClasses = {StatelessSessionVersioningTest.IdentityVersioned.class,
StatelessSessionVersioningTest.UUIDVersioned.class})
@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class)
public class StatelessSessionVersioningTest {
@Test void testIdentity(SessionFactoryScope scope) {
Dialect dialect = scope.getMetadataImplementor().getDatabase().getDialect();