提交 20d9bfee authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Limit range of TIME values by default and add property h2.unlimitedTimeRange

上级 2d9804ca
...@@ -364,6 +364,39 @@ public class SysProperties { ...@@ -364,6 +364,39 @@ public class SysProperties {
public static final boolean BIG_DECIMAL_IS_DECIMAL = public static final boolean BIG_DECIMAL_IS_DECIMAL =
Utils.getProperty("h2.bigDecimalIsDecimal", true); Utils.getProperty("h2.bigDecimalIsDecimal", true);
/**
* System property {@code h2.unlimitedTimeRange}, {@code false} by default.
*
* <p>
* Controls limits of TIME data type.
* </p>
*
* <table>
* <thead>
* <tr>
* <th>h2.unlimitedTimeRange</th>
* <th>Minimum TIME value</th>
* <th>Maximum TIME value</th>
* </tr>
* </thead>
* <tbody>
* <tr>
* <td>false</td>
* <td>00:00:00.000000000</td>
* <td>23:59:59.999999999</td>
* </tr>
* <tr>
* <td>true</td>
* <td>-2562047:47:16.854775808</td>
* <td>2562047:47:16.854775807</td>
* </tr>
* </tbody>
* </table>
*/
public static final boolean UNLIMITED_TIME_RANGE =
Utils.getProperty("h2.unlimitedTimeRange", false);
/** /**
* System property <code>h2.pgClientEncoding</code> (default: UTF-8).<br /> * System property <code>h2.pgClientEncoding</code> (default: UTF-8).<br />
* Default client encoding for PG server. It is used if the client does not * Default client encoding for PG server. It is used if the client does not
......
...@@ -9,6 +9,7 @@ import java.sql.PreparedStatement; ...@@ -9,6 +9,7 @@ import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Time; import java.sql.Time;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.engine.SysProperties;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.util.DateTimeUtils; import org.h2.util.DateTimeUtils;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
...@@ -48,6 +49,14 @@ public class ValueTime extends Value { ...@@ -48,6 +49,14 @@ public class ValueTime extends Value {
* @return the value * @return the value
*/ */
public static ValueTime fromNanos(long nanos) { public static ValueTime fromNanos(long nanos) {
if (!SysProperties.UNLIMITED_TIME_RANGE) {
if (nanos < 0L || nanos >= 86400000000000L) {
StringBuilder builder = new StringBuilder();
appendTime(builder, nanos, false);
throw DbException.get(ErrorCode.INVALID_DATETIME_CONSTANT_2,
"TIME", builder.toString());
}
}
return (ValueTime) Value.cache(new ValueTime(nanos)); return (ValueTime) Value.cache(new ValueTime(nanos));
} }
......
...@@ -14,6 +14,8 @@ import java.util.Calendar; ...@@ -14,6 +14,8 @@ import java.util.Calendar;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.TimeZone; import java.util.TimeZone;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.engine.SysProperties;
import org.h2.message.DbException;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.test.utils.AssertThrows; import org.h2.test.utils.AssertThrows;
import org.h2.util.DateTimeUtils; import org.h2.util.DateTimeUtils;
...@@ -116,35 +118,48 @@ public class TestDate extends TestBase { ...@@ -116,35 +118,48 @@ public class TestDate extends TestBase {
assertEquals("10:20:30", ValueTime.get(Time.valueOf("10:20:30")).getString()); assertEquals("10:20:30", ValueTime.get(Time.valueOf("10:20:30")).getString());
assertEquals("00:00:00", ValueTime.fromNanos(0).getString()); assertEquals("00:00:00", ValueTime.fromNanos(0).getString());
assertEquals("23:59:59", ValueTime.parse("23:59:59").getString()); assertEquals("23:59:59", ValueTime.parse("23:59:59").getString());
assertEquals("99:59:59", ValueTime.parse("99:59:59").getString()); assertEquals("11:22:33.444555666", ValueTime.parse("11:22:33.444555666").getString());
assertEquals("-00:10:10", ValueTime.parse("-00:10:10").getString()); if (SysProperties.UNLIMITED_TIME_RANGE) {
assertEquals("-99:02:03.001002003", assertEquals("99:59:59", ValueTime.parse("99:59:59").getString());
ValueTime.parse("-99:02:03.001002003").getString()); assertEquals("-00:10:10", ValueTime.parse("-00:10:10").getString());
assertEquals("-99:02:03.001002", assertEquals("-99:02:03.001002003",
ValueTime.parse("-99:02:03.001002000").getString()); ValueTime.parse("-99:02:03.001002003").getString());
assertEquals("-99:02:03", assertEquals("-99:02:03.001002",
ValueTime.parse("-99:02:03.0000000000001").getString()); ValueTime.parse("-99:02:03.001002000").getString());
assertEquals("1999999:59:59.999999999", assertEquals("-99:02:03",
ValueTime.parse("1999999:59:59.999999999").getString()); ValueTime.parse("-99:02:03.0000000000001").getString());
assertEquals("-1999999:59:59.999999999", assertEquals("1999999:59:59.999999999",
ValueTime.parse("-1999999:59:59.999999999").getString()); ValueTime.parse("1999999:59:59.999999999").getString());
assertEquals("2562047:47:16.854775807", assertEquals("-1999999:59:59.999999999",
ValueTime.fromNanos(Long.MAX_VALUE).getString()); ValueTime.parse("-1999999:59:59.999999999").getString());
assertEquals("-2562047:47:16.854775808", assertEquals("2562047:47:16.854775807",
ValueTime.fromNanos(Long.MIN_VALUE).getString()); ValueTime.fromNanos(Long.MAX_VALUE).getString());
assertEquals("-2562047:47:16.854775808",
ValueTime.fromNanos(Long.MIN_VALUE).getString());
} else {
try {
ValueTime.parse("-00:00:00.000000001");
fail();
} catch (DbException ex) {
assertEquals(ErrorCode.INVALID_DATETIME_CONSTANT_2, ex.getErrorCode());
}
try {
ValueTime.parse("24:00:00");
fail();
} catch (DbException ex) {
assertEquals(ErrorCode.INVALID_DATETIME_CONSTANT_2, ex.getErrorCode());
}
}
ValueTime t1 = ValueTime.parse("11:11:11"); ValueTime t1 = ValueTime.parse("11:11:11");
assertEquals("11:11:11", t1.getTime().toString()); assertEquals("11:11:11", t1.getTime().toString());
assertEquals("1970-01-01", t1.getDate().toString()); assertEquals("1970-01-01", t1.getDate().toString());
assertEquals("TIME '11:11:11'", t1.getSQL()); assertEquals("TIME '11:11:11'", t1.getSQL());
assertEquals("TIME '11:11:11'", t1.toString()); assertEquals("TIME '11:11:11'", t1.toString());
assertEquals(1, t1.getSignum()); assertEquals(1, t1.getSignum());
assertEquals(-1, t1.negate().getSignum());
assertEquals(0, t1.multiply(ValueInt.get(0)).getSignum()); assertEquals(0, t1.multiply(ValueInt.get(0)).getSignum());
assertEquals(0, t1.subtract(t1).getSignum()); assertEquals(0, t1.subtract(t1).getSignum());
assertEquals("05:35:35.5", t1.multiply(ValueDouble.get(0.5)).getString()); assertEquals("05:35:35.5", t1.multiply(ValueDouble.get(0.5)).getString());
assertEquals("22:22:22", t1.divide(ValueDouble.get(0.5)).getString()); assertEquals("22:22:22", t1.divide(ValueDouble.get(0.5)).getString());
assertEquals("-11:11:11", t1.negate().getString());
assertEquals("11:11:11", t1.negate().negate().getString());
assertEquals(Value.TIME, t1.getType()); assertEquals(Value.TIME, t1.getType());
long nanos = t1.getNanos(); long nanos = t1.getNanos();
assertEquals((int) ((nanos >>> 32) ^ nanos), t1.hashCode()); assertEquals((int) ((nanos >>> 32) ^ nanos), t1.hashCode());
...@@ -164,20 +179,26 @@ public class TestDate extends TestBase { ...@@ -164,20 +179,26 @@ public class TestDate extends TestBase {
ValueTime t2 = ValueTime.parse("22:22:22"); ValueTime t2 = ValueTime.parse("22:22:22");
assertFalse(t1.equals(t2)); assertFalse(t1.equals(t2));
assertFalse(t2.equals(t1)); assertFalse(t2.equals(t1));
assertEquals("33:33:33", t1.add(t2).getString());
assertEquals("33:33:33", t1.multiply(ValueInt.get(4)).subtract(t1).getString());
assertEquals(-1, t1.compareTo(t2, null)); assertEquals(-1, t1.compareTo(t2, null));
assertEquals(1, t2.compareTo(t1, null)); assertEquals(1, t2.compareTo(t1, null));
// can't convert using java.util.Date if (SysProperties.UNLIMITED_TIME_RANGE) {
assertEquals( assertEquals(-1, t1.negate().getSignum());
"1969-12-31 23:00:00.0", assertEquals("-11:11:11", t1.negate().getString());
ValueTime.parse("-1:00:00"). assertEquals("11:11:11", t1.negate().negate().getString());
convertTo(Value.TIMESTAMP).getString()); assertEquals("33:33:33", t1.add(t2).getString());
assertEquals( assertEquals("33:33:33", t1.multiply(ValueInt.get(4)).subtract(t1).getString());
"1970-01-01",
ValueTime.parse("-1:00:00"). // can't convert using java.util.Date
convertTo(Value.DATE).getString()); assertEquals(
"1969-12-31 23:00:00.0",
ValueTime.parse("-1:00:00").
convertTo(Value.TIMESTAMP).getString());
assertEquals(
"1970-01-01",
ValueTime.parse("-1:00:00").
convertTo(Value.DATE).getString());
}
} }
private void testValueTimestampWithTimezone() { private void testValueTimestampWithTimezone() {
...@@ -290,15 +311,9 @@ public class TestDate extends TestBase { ...@@ -290,15 +311,9 @@ public class TestDate extends TestBase {
assertEquals("2001-01-01 01:01:01.0", assertEquals("2001-01-01 01:01:01.0",
ValueTimestamp.parse("2001-01-01").add( ValueTimestamp.parse("2001-01-01").add(
ValueTime.parse("01:01:01")).getString()); ValueTime.parse("01:01:01")).getString());
assertEquals("2001-01-02 01:01:01.0",
ValueTimestamp.parse("2001-01-01").add(
ValueTime.parse("25:01:01")).getString());
assertEquals("1010-10-10 00:00:00.0", assertEquals("1010-10-10 00:00:00.0",
ValueTimestamp.parse("1010-10-10 10:10:10").subtract( ValueTimestamp.parse("1010-10-10 10:10:10").subtract(
ValueTime.parse("10:10:10")).getString()); ValueTime.parse("10:10:10")).getString());
assertEquals("1010-10-10 10:00:00.0",
ValueTimestamp.parse("1010-10-11 10:10:10").subtract(
ValueTime.parse("24:10:10")).getString());
assertEquals("-2001-01-01 01:01:01.0", assertEquals("-2001-01-01 01:01:01.0",
ValueTimestamp.parse("-2001-01-01").add( ValueTimestamp.parse("-2001-01-01").add(
ValueTime.parse("01:01:01")).getString()); ValueTime.parse("01:01:01")).getString());
...@@ -306,6 +321,15 @@ public class TestDate extends TestBase { ...@@ -306,6 +321,15 @@ public class TestDate extends TestBase {
ValueTimestamp.parse("-1010-10-10 10:10:10").subtract( ValueTimestamp.parse("-1010-10-10 10:10:10").subtract(
ValueTime.parse("10:10:10")).getString()); ValueTime.parse("10:10:10")).getString());
if (SysProperties.UNLIMITED_TIME_RANGE) {
assertEquals("2001-01-02 01:01:01.0",
ValueTimestamp.parse("2001-01-01").add(
ValueTime.parse("25:01:01")).getString());
assertEquals("1010-10-10 10:00:00.0",
ValueTimestamp.parse("1010-10-11 10:10:10").subtract(
ValueTime.parse("24:10:10")).getString());
}
assertEquals(0, DateTimeUtils.absoluteDayFromDateValue( assertEquals(0, DateTimeUtils.absoluteDayFromDateValue(
ValueTimestamp.parse("1970-01-01").getDateValue())); ValueTimestamp.parse("1970-01-01").getDateValue()));
assertEquals(0, ValueTimestamp.parse( assertEquals(0, ValueTimestamp.parse(
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论