HHH-15819 fix extract(offset hour from datetime)

bug noticed by @mrotteveel

improve the tests for extracting time zones
This commit is contained in:
Gavin 2022-12-05 13:35:32 +01:00 committed by Gavin King
parent e088738687
commit a4f301814b
5 changed files with 33 additions and 18 deletions

View File

@ -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;

View File

@ -4248,15 +4248,20 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> 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() + "]");
}
}

View File

@ -67,15 +67,12 @@ public class OffsetDateTimeJavaType extends AbstractTemporalJavaType<OffsetDateT
}
switch ( temporalPrecision ) {
case TIME: {
case TIME:
return jdbcTypeRegistry.getDescriptor( Types.TIME );
}
case DATE: {
case DATE:
return jdbcTypeRegistry.getDescriptor( Types.DATE );
}
default: {
default:
throw new IllegalArgumentException( "Unexpected jakarta.persistence.TemporalType : " + temporalPrecision );
}
}
}

View File

@ -10,13 +10,10 @@ import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.Calendar;
import java.util.TimeZone;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.descriptor.ValueBinder;

View File

@ -11,10 +11,12 @@ import java.sql.Time;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import org.hibernate.dialect.CockroachDialect;
import org.hamcrest.Matchers;
import org.hamcrest.number.IsCloseTo;
import org.hibernate.testing.orm.domain.StandardDomainModel;
import org.hibernate.testing.orm.domain.gambit.EntityOfBasics;
@ -28,8 +30,10 @@ import org.hibernate.testing.orm.junit.SkipForDialect;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.isOneOf;
@ -51,6 +55,7 @@ public class StandardFunctionTests {
entity.setTheDate( new Date( 74, 2, 25 ) );
entity.setTheTime( new Time( 20, 10, 8 ) );
entity.setTheTimestamp( new Timestamp( 121, 4, 27, 13, 22, 50, 123456789 ) );
entity.setTheZonedDateTime( ZonedDateTime.now().withZoneSameInstant( ZoneId.of("CET") ) );
em.persist(entity);
}
);
@ -632,10 +637,18 @@ public class StandardFunctionTests {
public void testExtractFunctionTimeZone(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
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) )
)
);
}