use custom-rendered datetime literals on MySQL instead of JDBC escapes
This commit is contained in:
parent
2aece6fb95
commit
4a87bc4bb8
|
@ -11,6 +11,11 @@ import java.sql.DatabaseMetaData;
|
|||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.PessimisticLockException;
|
||||
|
@ -104,6 +109,11 @@ 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.appendAsDate;
|
||||
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsLocalTime;
|
||||
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithMicros;
|
||||
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithMillis;
|
||||
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithNanos;
|
||||
|
||||
/**
|
||||
* A {@linkplain Dialect SQL dialect} for MySQL 5.7 and above.
|
||||
|
@ -765,6 +775,91 @@ public class MySQLDialect extends Dialect {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTemporalLiteralOffset() {
|
||||
return getMySQLVersion().isSameOrAfter(8,0,19);
|
||||
}
|
||||
|
||||
@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:
|
||||
if ( temporalAccessor instanceof ZonedDateTime ) {
|
||||
temporalAccessor = ((ZonedDateTime) temporalAccessor).toOffsetDateTime();
|
||||
}
|
||||
appender.appendSql( "timestamp '" );
|
||||
appendAsTimestampWithMicros( appender, temporalAccessor, supportsTemporalLiteralOffset(), jdbcTimeZone, false );
|
||||
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 '" );
|
||||
appendAsTimestampWithMicros( 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 supportsUnionAll() {
|
||||
return true;
|
||||
|
|
|
@ -47,6 +47,7 @@ public final class DateTimeUtils {
|
|||
public static final String FORMAT_STRING_TIMESTAMP_WITH_MILLIS_AND_OFFSET = FORMAT_STRING_TIMESTAMP_WITH_MILLIS + "XXX";
|
||||
public static final String FORMAT_STRING_TIMESTAMP_WITH_MICROS_AND_OFFSET = FORMAT_STRING_TIMESTAMP_WITH_MICROS + "XXX";
|
||||
public static final String FORMAT_STRING_TIMESTAMP_WITH_NANOS_AND_OFFSET = FORMAT_STRING_TIMESTAMP_WITH_NANOS + "XXX";
|
||||
public static final String FORMAT_STRING_TIMESTAMP_WITH_MICROS_AND_OFFSET_NOZ = FORMAT_STRING_TIMESTAMP_WITH_MICROS + "xxx";
|
||||
|
||||
public static final DateTimeFormatter DATE_TIME_FORMATTER_DATE = DateTimeFormatter.ofPattern( FORMAT_STRING_DATE, Locale.ENGLISH );
|
||||
public static final DateTimeFormatter DATE_TIME_FORMATTER_TIME_WITH_OFFSET = DateTimeFormatter.ofPattern( FORMAT_STRING_TIME_WITH_OFFSET, Locale.ENGLISH );
|
||||
|
@ -71,6 +72,10 @@ public final class DateTimeUtils {
|
|||
FORMAT_STRING_TIMESTAMP_WITH_MICROS_AND_OFFSET,
|
||||
Locale.ENGLISH
|
||||
);
|
||||
public static final DateTimeFormatter DATE_TIME_FORMATTER_TIMESTAMP_WITH_MICROS_AND_OFFSET_NOZ = DateTimeFormatter.ofPattern(
|
||||
FORMAT_STRING_TIMESTAMP_WITH_MICROS_AND_OFFSET_NOZ,
|
||||
Locale.ENGLISH
|
||||
);
|
||||
public static final DateTimeFormatter DATE_TIME_FORMATTER_TIMESTAMP_WITH_NANOS_AND_OFFSET = DateTimeFormatter.ofPattern(
|
||||
FORMAT_STRING_TIMESTAMP_WITH_NANOS_AND_OFFSET,
|
||||
Locale.ENGLISH
|
||||
|
@ -99,15 +104,14 @@ public final class DateTimeUtils {
|
|||
.optionalStart().appendZoneOrOffsetId().optionalEnd()
|
||||
.toFormatter();
|
||||
|
||||
private static final ThreadLocal<SimpleDateFormat> LOCAL_DATE_FORMAT = ThreadLocal.withInitial( () -> new SimpleDateFormat( FORMAT_STRING_DATE, Locale.ENGLISH ) );
|
||||
private static final ThreadLocal<SimpleDateFormat> LOCAL_TIME_FORMAT = ThreadLocal.withInitial( () -> new SimpleDateFormat( FORMAT_STRING_TIME, Locale.ENGLISH ) );
|
||||
private static final ThreadLocal<SimpleDateFormat> TIME_WITH_OFFSET_FORMAT = ThreadLocal.withInitial( () -> new SimpleDateFormat( FORMAT_STRING_TIME_WITH_OFFSET, Locale.ENGLISH ) );
|
||||
private static final ThreadLocal<SimpleDateFormat> TIMESTAMP_WITH_MILLIS_FORMAT = ThreadLocal.withInitial(
|
||||
() -> new SimpleDateFormat(
|
||||
FORMAT_STRING_TIMESTAMP_WITH_MILLIS,
|
||||
Locale.ENGLISH
|
||||
)
|
||||
);
|
||||
private static final ThreadLocal<SimpleDateFormat> LOCAL_DATE_FORMAT =
|
||||
ThreadLocal.withInitial( () -> new SimpleDateFormat( FORMAT_STRING_DATE, Locale.ENGLISH ) );
|
||||
private static final ThreadLocal<SimpleDateFormat> LOCAL_TIME_FORMAT =
|
||||
ThreadLocal.withInitial( () -> new SimpleDateFormat( FORMAT_STRING_TIME, Locale.ENGLISH ) );
|
||||
private static final ThreadLocal<SimpleDateFormat> TIME_WITH_OFFSET_FORMAT =
|
||||
ThreadLocal.withInitial( () -> new SimpleDateFormat( FORMAT_STRING_TIME_WITH_OFFSET, Locale.ENGLISH ) );
|
||||
private static final ThreadLocal<SimpleDateFormat> TIMESTAMP_WITH_MILLIS_FORMAT =
|
||||
ThreadLocal.withInitial( () -> new SimpleDateFormat( FORMAT_STRING_TIMESTAMP_WITH_MILLIS, Locale.ENGLISH ) );
|
||||
|
||||
/**
|
||||
* Pattern used for parsing literal offset datetimes in HQL.
|
||||
|
@ -156,6 +160,24 @@ public final class DateTimeUtils {
|
|||
);
|
||||
}
|
||||
|
||||
public static void appendAsTimestampWithMicros(
|
||||
SqlAppender appender,
|
||||
TemporalAccessor temporalAccessor,
|
||||
boolean supportsOffset,
|
||||
TimeZone jdbcTimeZone,
|
||||
boolean allowZforZeroOffset) {
|
||||
appendAsTimestamp(
|
||||
appender,
|
||||
temporalAccessor,
|
||||
supportsOffset,
|
||||
jdbcTimeZone,
|
||||
DATE_TIME_FORMATTER_TIMESTAMP_WITH_MICROS,
|
||||
allowZforZeroOffset
|
||||
? DATE_TIME_FORMATTER_TIMESTAMP_WITH_MICROS_AND_OFFSET
|
||||
: DATE_TIME_FORMATTER_TIMESTAMP_WITH_MICROS_AND_OFFSET_NOZ
|
||||
);
|
||||
}
|
||||
|
||||
public static void appendAsTimestampWithMillis(
|
||||
SqlAppender appender,
|
||||
TemporalAccessor temporalAccessor,
|
||||
|
|
Loading…
Reference in New Issue