From 8ddb40fa77d6221d23ce94a1b6c0d6813c22f08e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Kuruc?= Date: Wed, 28 Aug 2024 12:15:47 +0200 Subject: [PATCH] HHH-18531 Fix for Informix timestamp literal error --- .../community/dialect/InformixDialect.java | 68 +++++++++++++++++++ .../test/temporal/FractionalSecondsTests.java | 3 + .../JavaTimeFractionalSecondsTests.java | 3 + 3 files changed, 74 insertions(+) diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixDialect.java index b269c9206b..d31b169b93 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixDialect.java @@ -7,6 +7,9 @@ package org.hibernate.community.dialect; import java.sql.Types; +import java.time.temporal.TemporalAccessor; +import java.util.Date; +import java.util.TimeZone; import org.hibernate.boot.Metadata; import org.hibernate.boot.model.FunctionContributions; @@ -74,6 +77,8 @@ import org.hibernate.type.descriptor.sql.internal.CapacityDependentDdlType; import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; import org.hibernate.type.spi.TypeConfiguration; +import jakarta.persistence.TemporalType; + import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate; import static org.hibernate.type.SqlTypes.BIGINT; import static org.hibernate.type.SqlTypes.BINARY; @@ -88,6 +93,14 @@ import static org.hibernate.type.SqlTypes.TIMESTAMP_WITH_TIMEZONE; import static org.hibernate.type.SqlTypes.TINYINT; import static org.hibernate.type.SqlTypes.VARBINARY; import static org.hibernate.type.SqlTypes.VARCHAR; +import static org.hibernate.type.descriptor.DateTimeUtils.JDBC_ESCAPE_END; +import static org.hibernate.type.descriptor.DateTimeUtils.JDBC_ESCAPE_START_DATE; +import static org.hibernate.type.descriptor.DateTimeUtils.JDBC_ESCAPE_START_TIME; +import static org.hibernate.type.descriptor.DateTimeUtils.JDBC_ESCAPE_START_TIMESTAMP; +import static org.hibernate.type.descriptor.DateTimeUtils.appendAsDate; +import static org.hibernate.type.descriptor.DateTimeUtils.appendAsLocalTime; +import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTime; +import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithMicros; /** * Dialect for Informix 7.31.UD3 with Informix @@ -234,6 +247,11 @@ public class InformixDialect extends Dialect { return 5; } + @Override + public boolean doesRoundTemporalOnOverflow() { + return false; + } + @Override public int getFloatPrecision() { return 8; @@ -713,6 +731,56 @@ public class InformixDialect extends Dialect { .replace("S", "%F1"); } + @Override + public void appendDateTimeLiteral( + SqlAppender appender, + TemporalAccessor temporalAccessor, + TemporalType precision, + TimeZone jdbcTimeZone) { + switch ( precision ) { + case DATE: + appender.appendSql( JDBC_ESCAPE_START_DATE ); + appendAsDate( appender, temporalAccessor ); + appender.appendSql( JDBC_ESCAPE_END ); + break; + case TIME: + appender.appendSql( JDBC_ESCAPE_START_TIME ); + appendAsTime( appender, temporalAccessor, supportsTemporalLiteralOffset(), jdbcTimeZone ); + appender.appendSql( JDBC_ESCAPE_END ); + break; + case TIMESTAMP: + appender.appendSql( JDBC_ESCAPE_START_TIMESTAMP ); + appendAsTimestampWithMicros( appender, temporalAccessor, supportsTemporalLiteralOffset(), jdbcTimeZone ); + appender.appendSql( JDBC_ESCAPE_END ); + break; + default: + throw new IllegalArgumentException(); + } + } + + @Override + public void appendDateTimeLiteral(SqlAppender appender, Date date, TemporalType precision, TimeZone jdbcTimeZone) { + switch ( precision ) { + case DATE: + appender.appendSql( JDBC_ESCAPE_START_DATE ); + appendAsDate( appender, date ); + appender.appendSql( JDBC_ESCAPE_END ); + break; + case TIME: + appender.appendSql( JDBC_ESCAPE_START_TIME ); + appendAsLocalTime( appender, date ); + appender.appendSql( JDBC_ESCAPE_END ); + break; + case TIMESTAMP: + appender.appendSql( JDBC_ESCAPE_START_TIMESTAMP ); + appendAsTimestampWithMicros( appender, date, jdbcTimeZone ); + appender.appendSql( JDBC_ESCAPE_END ); + break; + default: + throw new IllegalArgumentException(); + } + } + @Override public String getSelectClauseNullString(int sqlType, TypeConfiguration typeConfiguration) { DdlType descriptor = typeConfiguration.getDdlTypeRegistry().getDescriptor( sqlType ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/temporal/FractionalSecondsTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/temporal/FractionalSecondsTests.java index 7fe9ae3ff9..3bb0bd086e 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/temporal/FractionalSecondsTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/temporal/FractionalSecondsTests.java @@ -16,6 +16,7 @@ import java.time.ZonedDateTime; import org.hibernate.annotations.FractionalSeconds; import org.hibernate.boot.spi.MetadataImplementor; import org.hibernate.community.dialect.AltibaseDialect; +import org.hibernate.community.dialect.InformixDialect; import org.hibernate.dialect.CockroachDialect; import org.hibernate.dialect.DerbyDialect; import org.hibernate.dialect.Dialect; @@ -121,6 +122,7 @@ public class FractionalSecondsTests { @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 = AltibaseDialect.class, reason = "Altibase does not support specifying a precision on timestamps") + @SkipForDialect(dialectClass = InformixDialect.class, reason = "Informix only supports precision from 1 to 5") void testUsage0(SessionFactoryScope scope) { final Instant start = Instant.now(); @@ -172,6 +174,7 @@ public class FractionalSecondsTests { @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") + @SkipForDialect(dialectClass = InformixDialect.class, reason = "Informix only supports precision from 1 to 5") void testUsage9(SessionFactoryScope scope) { final Instant start = Instant.now(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/temporal/JavaTimeFractionalSecondsTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/temporal/JavaTimeFractionalSecondsTests.java index b84fbda1ea..0e40a61fc1 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/temporal/JavaTimeFractionalSecondsTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/temporal/JavaTimeFractionalSecondsTests.java @@ -17,6 +17,7 @@ import org.hibernate.annotations.FractionalSeconds; import org.hibernate.annotations.JdbcTypeCode; import org.hibernate.boot.spi.MetadataImplementor; import org.hibernate.community.dialect.AltibaseDialect; +import org.hibernate.community.dialect.InformixDialect; import org.hibernate.dialect.CockroachDialect; import org.hibernate.dialect.DerbyDialect; import org.hibernate.dialect.Dialect; @@ -123,6 +124,7 @@ public class JavaTimeFractionalSecondsTests { @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 = AltibaseDialect.class, reason = "Altibase does not support specifying a precision on timestamps") + @SkipForDialect(dialectClass = InformixDialect.class, reason = "Informix only supports precision from 1 to 5") void testUsage0(SessionFactoryScope scope) { final Instant start = Instant.now(); @@ -174,6 +176,7 @@ public class JavaTimeFractionalSecondsTests { @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") + @SkipForDialect(dialectClass = InformixDialect.class, reason = "Informix only supports precision from 1 to 5") void testUsage9(SessionFactoryScope scope) { final Instant start = Instant.now();