From a4f301814b69fcf5cd386c7c815414691beddedc Mon Sep 17 00:00:00 2001 From: Gavin Date: Mon, 5 Dec 2022 13:35:32 +0100 Subject: [PATCH] HHH-15819 fix extract(offset hour from datetime) bug noticed by @mrotteveel improve the tests for extracting time zones --- .../util/config/ConfigurationHelper.java | 1 - .../hql/internal/SemanticQueryBuilder.java | 7 ++++- .../java/OffsetDateTimeJavaType.java | 9 ++---- ...nstantAsTimestampWithTimeZoneJdbcType.java | 3 -- .../test/query/hql/StandardFunctionTests.java | 31 ++++++++++++++----- 5 files changed, 33 insertions(+), 18 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/config/ConfigurationHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/config/ConfigurationHelper.java index dea60d2ec3..e92e6829ad 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/config/ConfigurationHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/config/ConfigurationHelper.java @@ -6,7 +6,6 @@ */ package org.hibernate.internal.util.config; -import java.sql.Types; import java.util.HashMap; import java.util.Iterator; import java.util.Locale; diff --git a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java index 7364d791e4..796328c09c 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java @@ -4248,15 +4248,20 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implem final NodeBuilder nodeBuilder = creationContext.getNodeBuilder(); switch ( ( (TerminalNode) ctx.getChild( ctx.getChildCount() - 1 ) ).getSymbol().getType() ) { case HqlParser.TIMEZONE_HOUR: + case HqlParser.HOUR: return new SqmExtractUnit<>( TIMEZONE_HOUR, resolveExpressibleTypeBasic( Integer.class ), nodeBuilder ); case HqlParser.TIMEZONE_MINUTE: + case HqlParser.MINUTE: return new SqmExtractUnit<>( TIMEZONE_MINUTE, resolveExpressibleTypeBasic( Integer.class ), nodeBuilder ); - default: + case HqlParser.OFFSET: return new SqmExtractUnit<>( OFFSET, resolveExpressibleTypeBasic( ZoneOffset.class ), nodeBuilder ); + default: + // should never happen + throw new ParsingException("Unsupported time zone field [" + ctx.getText() + "]"); } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetDateTimeJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetDateTimeJavaType.java index e5e229fb94..78be547b9e 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetDateTimeJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetDateTimeJavaType.java @@ -67,15 +67,12 @@ public class OffsetDateTimeJavaType extends AbstractTemporalJavaType { - session.createQuery("select extract(offset hour from e.theZonedDateTime) from EntityOfBasics e") - .list(); - session.createQuery("select extract(offset minute from e.theZonedDateTime) from EntityOfBasics e") - .list(); + assertThat( + session.createQuery("select extract(offset hour from e.theZonedDateTime) from EntityOfBasics e") + .getResultList() + .get(0), + anyOf( nullValue(), instanceOf( Integer.class ) ) + ); + assertThat( + session.createQuery("select extract(offset minute from e.theZonedDateTime) from EntityOfBasics e") + .getResultList() + .get(0), + anyOf( nullValue(), instanceOf( Integer.class ) ) + ); } ); } @@ -645,8 +658,12 @@ public class StandardFunctionTests { @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsFormat.class, comment = "We extract the offset with a format function") public void testExtractFunctionTimeZoneOffset(SessionFactoryScope scope) { scope.inTransaction( - session -> session.createQuery( "select extract(offset from e.theZonedDateTime) from EntityOfBasics e") - .list() + session -> assertThat( + session.createQuery( "select extract(offset from e.theZonedDateTime) from EntityOfBasics e") + .getResultList() + .get( 0 ), + anyOf( nullValue(), instanceOf(ZoneOffset.class) ) + ) ); }