From 43745c93720455f4cfbaea4840a1fcd0f9f92e78 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 c094d8a3bf..fca2343427 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; @@ -718,6 +736,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 a2bf48270a..7819ad8de4 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 @@ -17,6 +17,7 @@ import java.time.temporal.ChronoUnit; 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.community.dialect.DerbyDialect; import org.hibernate.dialect.Dialect; @@ -128,6 +129,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 Dialect dialect = scope.getSessionFactory().getJdbcServices().getDialect(); final Instant start; @@ -191,6 +193,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 Dialect dialect = scope.getSessionFactory().getJdbcServices().getDialect(); final Instant start; 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 8efb39bce5..7377d16cf9 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 @@ -18,6 +18,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.community.dialect.DerbyDialect; import org.hibernate.dialect.Dialect; @@ -130,6 +131,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 Dialect dialect = scope.getSessionFactory().getJdbcServices().getDialect(); final Instant start; @@ -193,6 +195,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 Dialect dialect = scope.getSessionFactory().getJdbcServices().getDialect(); final Instant start;