HHH-16035 use custom-rendered datetime literals on DB2 instad of JDBC escapes

The JDBC escapes didn't play so well with duration arithmetic.
This commit is contained in:
Gavin 2023-01-14 01:42:18 +01:00 committed by Gavin King
parent 8f29ae95c9
commit 2aece6fb95
3 changed files with 92 additions and 6 deletions

View File

@ -11,7 +11,11 @@ import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.time.temporal.TemporalAccessor;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import org.hibernate.LockOptions;
import org.hibernate.boot.model.FunctionContributions;
@ -94,6 +98,10 @@ 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.SqlTypes.VARCHAR;
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsDate;
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsLocalTime;
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithMillis;
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithNanos;
/**
* A {@linkplain Dialect SQL dialect} for DB2 for LUW (Linux, Unix, and Windows) version 10.5 and above.
@ -526,6 +534,83 @@ public class DB2Dialect extends Dialect {
return pattern.toString();
}
@Override
public void appendDateTimeLiteral(
SqlAppender appender,
TemporalAccessor temporalAccessor,
TemporalType precision,
TimeZone jdbcTimeZone) {
switch ( precision ) {
case DATE:
appender.appendSql( "date '" );
appendAsDate( appender, temporalAccessor );
appender.appendSql( '\'' );
break;
case TIME:
appender.appendSql( "time '" );
appendAsLocalTime( appender, temporalAccessor );
appender.appendSql( '\'' );
break;
case TIMESTAMP:
appender.appendSql( "timestamp '" );
appendAsTimestampWithNanos( appender, temporalAccessor, false, jdbcTimeZone );
appender.appendSql( '\'' );
break;
default:
throw new IllegalArgumentException();
}
}
@Override
public void appendDateTimeLiteral(SqlAppender appender, Date date, TemporalType precision, TimeZone jdbcTimeZone) {
switch ( precision ) {
case DATE:
appender.appendSql( "date '" );
appendAsDate( appender, date );
appender.appendSql( '\'' );
break;
case TIME:
appender.appendSql( "time '" );
appendAsLocalTime( appender, date );
appender.appendSql( '\'' );
break;
case TIMESTAMP:
appender.appendSql( "timestamp '" );
appendAsTimestampWithNanos( appender, date, jdbcTimeZone );
appender.appendSql( '\'' );
break;
default:
throw new IllegalArgumentException();
}
}
@Override
public void appendDateTimeLiteral(
SqlAppender appender,
Calendar calendar,
TemporalType precision,
TimeZone jdbcTimeZone) {
switch ( precision ) {
case DATE:
appender.appendSql( "date '" );
appendAsDate( appender, calendar );
appender.appendSql( '\'' );
break;
case TIME:
appender.appendSql( "time '" );
appendAsLocalTime( appender, calendar );
appender.appendSql( '\'' );
break;
case TIMESTAMP:
appender.appendSql( "timestamp '" );
appendAsTimestampWithMillis( appender, calendar, jdbcTimeZone );
appender.appendSql( '\'' );
break;
default:
throw new IllegalArgumentException();
}
}
@Override
public boolean dropConstraints() {
return false;

View File

@ -239,6 +239,7 @@ 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.appendAsTimestampWithMillis;
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithNanos;
@ -5083,7 +5084,7 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
break;
case TIME:
appender.appendSql( JDBC_ESCAPE_START_TIME );
appendAsTime( appender, date );
appendAsLocalTime( appender, date );
appender.appendSql( JDBC_ESCAPE_END );
break;
case TIMESTAMP:
@ -5113,7 +5114,7 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
break;
case TIME:
appender.appendSql( JDBC_ESCAPE_START_TIME );
appendAsTime( appender, calendar );
appendAsLocalTime( appender, calendar );
appender.appendSql( JDBC_ESCAPE_END );
break;
case TIMESTAMP:

View File

@ -867,8 +867,8 @@ public class FunctionTests {
assertThat( session.createQuery("select cast('1911-10-09 12:13:14.123' as Timestamp)").getSingleResult(), instanceOf(Timestamp.class) );
assertThat( session.createQuery("select cast(date 1911-10-09 as String)").getSingleResult(), is("1911-10-09") );
assertThat( session.createQuery("select cast(time 12:13:14 as String)").getSingleResult(), anyOf( is("12:13:14"), is("12:13:14.0000") ) );
assertThat( (String) session.createQuery("select cast(datetime 1911-10-09 12:13:14 as String)").getSingleResult(), startsWith("1911-10-09 12:13:14") );
assertThat( session.createQuery("select cast(time 12:13:14 as String)").getSingleResult(), anyOf( is("12:13:14"), is("12:13:14.0000"), is("12.13.14") ) );
assertThat( (String) session.createQuery("select cast(datetime 1911-10-09 12:13:14 as String)").getSingleResult(), anyOf( startsWith("1911-10-09 12:13:14"), startsWith("1911-10-09-12.13.14") ) );
assertThat( session.createQuery("select cast(1 as NumericBoolean)").getSingleResult(), is(true) );
assertThat( session.createQuery("select cast(0 as NumericBoolean)").getSingleResult(), is(false) );
@ -939,7 +939,7 @@ public class FunctionTests {
.list();
assertThat( session.createQuery("select str(69)").getSingleResult(), is("69") );
assertThat( session.createQuery("select str(date 1911-10-09)").getSingleResult(), is("1911-10-09") );
assertThat( session.createQuery("select str(time 12:13:14)").getSingleResult(), anyOf( is( "12:13:14"), is( "12:13:14.0000") ) );
assertThat( session.createQuery("select str(time 12:13:14)").getSingleResult(), anyOf( is( "12:13:14"), is( "12:13:14.0000"), is( "12.13.14") ) );
}
);
}
@ -1336,7 +1336,7 @@ public class FunctionTests {
);
}
@Test @SkipForDialect(dialectClass = DB2Dialect.class)
@Test
public void testDurationArithmeticWithLiterals(SessionFactoryScope scope) {
scope.inTransaction(
session -> {