提交 dfc350ac authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Fix possible overflow in scale of timestamps

上级 d4ac543e
......@@ -6,6 +6,7 @@
*/
package org.h2.util;
import java.math.BigDecimal;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
......@@ -19,6 +20,7 @@ import org.h2.engine.Mode;
import org.h2.message.DbException;
import org.h2.value.Value;
import org.h2.value.ValueDate;
import org.h2.value.ValueDecimal;
import org.h2.value.ValueNull;
import org.h2.value.ValueTime;
import org.h2.value.ValueTimestamp;
......@@ -1448,4 +1450,19 @@ public class DateTimeUtils {
return b.toString();
}
/**
* Converts scale of nanoseconds.
*
* @param nanosOfDay nanoseconds of day
* @param scale fractional seconds precision
* @return scaled value
*/
public static long convertScale(long nanosOfDay, int scale) {
BigDecimal bd = BigDecimal.valueOf(nanosOfDay);
bd = bd.movePointLeft(9);
bd = ValueDecimal.setScale(bd, scale);
bd = bd.movePointRight(9);
return bd.longValue();
}
}
......@@ -5,7 +5,6 @@
*/
package org.h2.value;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
......@@ -216,15 +215,16 @@ public class ValueTimestamp extends Value {
throw DbException.getInvalidValueException("scale", targetScale);
}
long n = timeNanos;
BigDecimal bd = BigDecimal.valueOf(n);
bd = bd.movePointLeft(9);
bd = ValueDecimal.setScale(bd, targetScale);
bd = bd.movePointRight(9);
long n2 = bd.longValue();
long n2 = DateTimeUtils.convertScale(n, targetScale);
if (n2 == n) {
return this;
}
return fromDateValueAndNanos(dateValue, n2);
long dv = dateValue;
if (n2 >= DateTimeUtils.NANOS_PER_DAY) {
n2 -= DateTimeUtils.NANOS_PER_DAY;
dv = DateTimeUtils.dateValueFromAbsoluteDay(DateTimeUtils.absoluteDayFromDateValue(dateValue) + 1);
}
return fromDateValueAndNanos(dv, n2);
}
@Override
......
......@@ -5,7 +5,6 @@
*/
package org.h2.value;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
......@@ -205,15 +204,16 @@ public class ValueTimestampTimeZone extends Value {
throw DbException.getInvalidValueException("scale", targetScale);
}
long n = timeNanos;
BigDecimal bd = BigDecimal.valueOf(n);
bd = bd.movePointLeft(9);
bd = ValueDecimal.setScale(bd, targetScale);
bd = bd.movePointRight(9);
long n2 = bd.longValue();
long n2 = DateTimeUtils.convertScale(n, targetScale);
if (n2 == n) {
return this;
}
return fromDateValueAndNanos(dateValue, n2, timeZoneOffsetMins);
long dv = dateValue;
if (n2 >= DateTimeUtils.NANOS_PER_DAY) {
n2 -= DateTimeUtils.NANOS_PER_DAY;
dv = DateTimeUtils.dateValueFromAbsoluteDay(DateTimeUtils.absoluteDayFromDateValue(dateValue) + 1);
}
return fromDateValueAndNanos(dv, n2, timeZoneOffsetMins);
}
@Override
......
......@@ -84,5 +84,16 @@ SELECT T7, T8, T9 FROM TEST;
> 2000-01-01 08:00:00.1234568+00 2000-01-01 08:00:00.12345679+00 2000-01-01 08:00:00.123456789+00
> rows: 1
DELETE FROM TEST;
> update count: 1
INSERT INTO TEST(T0) VALUES ('2000-01-01 23:59:59.999999999Z');
> update count: 1
SELECT T0 FROM TEST;
> T0
> ------------------------
> 2000-01-02 00:00:00.0+00
DROP TABLE TEST;
> ok
......@@ -77,5 +77,16 @@ SELECT T7, T8, T9 FROM TEST;
> 2000-01-01 08:00:00.1234568 2000-01-01 08:00:00.12345679 2000-01-01 08:00:00.123456789
> rows: 1
DELETE FROM TEST;
> update count: 1
INSERT INTO TEST(T0) VALUES ('2000-01-01 23:59:59.999999999');
> update count: 1
SELECT T0 FROM TEST;
> T0
> ---------------------
> 2000-01-02 00:00:00.0
DROP TABLE TEST;
> ok
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论