Skip to content

Commit 720d7ce

Browse files
committed
try syncing duration handling in Cockroach with Postgres
1 parent 301c38b commit 720d7ce

File tree

1 file changed

+14
-17
lines changed

1 file changed

+14
-17
lines changed

hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -815,11 +815,15 @@ public String translateExtractField(TemporalUnit unit) {
815815

816816
/**
817817
* {@code microsecond} is the smallest unit for an {@code interval},
818-
* and the highest precision for a {@code timestamp}.
818+
* and the highest precision for a {@code timestamp}, so we could
819+
* use it as the "native" precision, but it's more convenient to use
820+
* whole seconds (with the fractional part), since we want to use
821+
* {@code extract(epoch from ...)} in our emulation of
822+
* {@code timestampdiff()}.
819823
*/
820824
@Override
821825
public long getFractionalSecondPrecisionInNanos() {
822-
return 1_000; //microseconds
826+
return 1_000_000_000; //seconds
823827
}
824828

825829
@Override @SuppressWarnings("deprecation")
@@ -831,8 +835,8 @@ public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType,
831835

832836
private static String intervalPattern(TemporalUnit unit) {
833837
return switch (unit) {
834-
case NATIVE -> "(?2)*interval '1 microsecond'";
835838
case NANOSECOND -> "(?2)/1e3*interval '1 microsecond'";
839+
case NATIVE -> "(?2)*interval '1 second'";
836840
case QUARTER -> "(?2)*interval '3 month'"; // quarter is not supported in interval literals
837841
case WEEK -> "(?2)*interval '7 day'"; // week is not supported in interval literals
838842
default -> "(?2)*interval '1 " + unit + "'";
@@ -849,9 +853,9 @@ public String timestampdiffPattern(TemporalUnit unit, TemporalType fromTemporalT
849853
// results in an integer number of days
850854
// instead of an INTERVAL
851855
return switch (unit) {
852-
case YEAR, MONTH, QUARTER ->
853-
// age only supports timestamptz, so we have to cast the date expressions
854-
"extract(" + translateDurationField( unit )
856+
case YEAR, MONTH, QUARTER
857+
-> "extract(" + translateDurationField( unit )
858+
// age only supports timestamptz, so we have to cast the date expressions
855859
+ " from age(cast(?3 as timestamptz),cast(?2 as timestamptz)))";
856860
default -> "(?3-?2)" + DAY.conversionFactor( unit, this );
857861
};
@@ -863,28 +867,21 @@ public String timestampdiffPattern(TemporalUnit unit, TemporalType fromTemporalT
863867
case MONTH -> "(extract(year from ?3-?2)*12+extract(month from ?3-?2))";
864868
case WEEK -> "(extract(day from ?3-?2)/7)"; // week is not supported by extract() when the argument is a duration
865869
case DAY -> "extract(day from ?3-?2)";
866-
//in order to avoid multiple calls to extract(),
867-
//we use extract(epoch from x - y) * factor for
868-
//all the following units:
869870
// Note that CockroachDB also has an extract_duration function which returns an int,
870871
// but we don't use that here because it is deprecated since v20.
871872
// We need to use round() instead of cast(... as int) because extract epoch returns
872-
// float8 which can cause loss-of-precision in some cases
873+
// float8 which can cause loss of precision in some cases
873874
// https://github.com/cockroachdb/cockroach/issues/72523
875+
// in order to avoid multiple calls to extract(),
876+
// we use extract(epoch from x - y) * factor for
877+
// all the following units:
874878
case HOUR, MINUTE, SECOND, NANOSECOND, NATIVE ->
875879
"round(extract(epoch from ?3-?2)" + EPOCH.conversionFactor( unit, this ) + ")::int";
876880
default -> throw new SemanticException( "Unrecognized field: " + unit );
877881
};
878882
}
879883
}
880884

881-
@Override
882-
public String translateDurationField(TemporalUnit unit) {
883-
return unit==NATIVE
884-
? "microsecond"
885-
: super.translateDurationField( unit );
886-
}
887-
888885
@Override
889886
public void appendDatetimeFormat(SqlAppender appender, String format) {
890887
appender.appendSql( SpannerDialect.datetimeFormat( format ).result() );

0 commit comments

Comments
 (0)