提交 5a481f85 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Align precision and display size of date-time columns with JDBC specification

上级 a64c34d1
...@@ -4433,7 +4433,6 @@ public class Parser { ...@@ -4433,7 +4433,6 @@ public class Parser {
if (t == Value.TIME || t == Value.TIMESTAMP || t == Value.TIMESTAMP_TZ) { if (t == Value.TIME || t == Value.TIMESTAMP || t == Value.TIMESTAMP_TZ) {
if (originalScale >= 0) { if (originalScale >= 0) {
scale = originalScale; scale = originalScale;
precision = dataType.defaultPrecision;
switch (t) { switch (t) {
case Value.TIME: case Value.TIME:
if (original.equals("TIME WITHOUT TIME ZONE")) { if (original.equals("TIME WITHOUT TIME ZONE")) {
...@@ -4441,7 +4440,7 @@ public class Parser { ...@@ -4441,7 +4440,7 @@ public class Parser {
} else { } else {
original = original + '(' + originalScale + ')'; original = original + '(' + originalScale + ')';
} }
displaySize = ValueTime.getDisplaySize(originalScale); precision = displaySize = ValueTime.getDisplaySize(originalScale);
break; break;
case Value.TIMESTAMP: case Value.TIMESTAMP:
if (original.equals("TIMESTAMP WITHOUT TIME ZONE")) { if (original.equals("TIMESTAMP WITHOUT TIME ZONE")) {
...@@ -4449,11 +4448,11 @@ public class Parser { ...@@ -4449,11 +4448,11 @@ public class Parser {
} else { } else {
original = original + '(' + originalScale + ')'; original = original + '(' + originalScale + ')';
} }
displaySize = ValueTimestamp.getDisplaySize(originalScale); precision = displaySize = ValueTimestamp.getDisplaySize(originalScale);
break; break;
case Value.TIMESTAMP_TZ: case Value.TIMESTAMP_TZ:
original = "TIMESTAMP(" + originalScale + ") WITH TIME ZONE"; original = "TIMESTAMP(" + originalScale + ") WITH TIME ZONE";
displaySize = ValueTimestampTimeZone.getDisplaySize(originalScale); precision = displaySize = ValueTimestampTimeZone.getDisplaySize(originalScale);
break; break;
} }
} }
......
...@@ -2590,7 +2590,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -2590,7 +2590,7 @@ public class Function extends Expression implements FunctionCall {
t = Value.DATE; t = Value.DATE;
p = ValueDate.PRECISION; p = ValueDate.PRECISION;
s = 0; s = 0;
d = ValueDate.DISPLAY_SIZE; d = ValueDate.PRECISION;
} }
break; break;
case ABS: case ABS:
......
...@@ -295,10 +295,10 @@ public class TableLink extends Table { ...@@ -295,10 +295,10 @@ public class TableLink extends Table {
precision = Math.max(ValueDate.PRECISION, precision); precision = Math.max(ValueDate.PRECISION, precision);
break; break;
case Types.TIMESTAMP: case Types.TIMESTAMP:
precision = Math.max(ValueTimestamp.PRECISION, precision); precision = Math.max(ValueTimestamp.MAXIMUM_PRECISION, precision);
break; break;
case Types.TIME: case Types.TIME:
precision = Math.max(ValueTime.PRECISION, precision); precision = Math.max(ValueTime.MAXIMUM_PRECISION, precision);
break; break;
} }
return precision; return precision;
......
...@@ -1421,7 +1421,7 @@ public class DateTimeUtils { ...@@ -1421,7 +1421,7 @@ public class DateTimeUtils {
* @return formatted string * @return formatted string
*/ */
public static String timestampTimeZoneToString(long dateValue, long timeNanos, short timeZoneOffsetMins) { public static String timestampTimeZoneToString(long dateValue, long timeNanos, short timeZoneOffsetMins) {
StringBuilder buff = new StringBuilder(ValueTimestampTimeZone.DISPLAY_SIZE); StringBuilder buff = new StringBuilder(ValueTimestampTimeZone.MAXIMUM_PRECISION);
appendDate(buff, dateValue); appendDate(buff, dateValue);
buff.append(' '); buff.append(' ');
appendTime(buff, timeNanos, true); appendTime(buff, timeNanos, true);
......
...@@ -282,24 +282,22 @@ public class DataType { ...@@ -282,24 +282,22 @@ public class DataType {
24 24
); );
add(Value.TIME, Types.TIME, add(Value.TIME, Types.TIME,
createDate(ValueTime.PRECISION, "TIME", createDate(ValueTime.MAXIMUM_PRECISION, ValueTime.DEFAULT_PRECISION,
true, ValueTime.DEFAULT_SCALE, ValueTime.MAXIMUM_SCALE, "TIME", true, ValueTime.DEFAULT_SCALE, ValueTime.MAXIMUM_SCALE),
ValueTime.DISPLAY_SIZE),
new String[]{"TIME", "TIME WITHOUT TIME ZONE"}, new String[]{"TIME", "TIME WITHOUT TIME ZONE"},
// 24 for ValueTime, 32 for java.sql.Time // 24 for ValueTime, 32 for java.sql.Time
56 56
); );
add(Value.DATE, Types.DATE, add(Value.DATE, Types.DATE,
createDate(ValueDate.PRECISION, "DATE", createDate(ValueDate.PRECISION, ValueDate.PRECISION,
false, 0, 0, ValueDate.DISPLAY_SIZE), "DATE", false, 0, 0),
new String[]{"DATE"}, new String[]{"DATE"},
// 24 for ValueDate, 32 for java.sql.Data // 24 for ValueDate, 32 for java.sql.Data
56 56
); );
add(Value.TIMESTAMP, Types.TIMESTAMP, add(Value.TIMESTAMP, Types.TIMESTAMP,
createDate(ValueTimestamp.PRECISION, "TIMESTAMP", createDate(ValueTimestamp.MAXIMUM_PRECISION, ValueTimestamp.DEFAULT_PRECISION,
true, ValueTimestamp.DEFAULT_SCALE, ValueTimestamp.MAXIMUM_SCALE, "TIMESTAMP", true, ValueTimestamp.DEFAULT_SCALE, ValueTimestamp.MAXIMUM_SCALE),
ValueTimestamp.DISPLAY_SIZE),
new String[]{"TIMESTAMP", "TIMESTAMP WITHOUT TIME ZONE", new String[]{"TIMESTAMP", "TIMESTAMP WITHOUT TIME ZONE",
"DATETIME", "DATETIME2", "SMALLDATETIME"}, "DATETIME", "DATETIME2", "SMALLDATETIME"},
// 24 for ValueTimestamp, 32 for java.sql.Timestamp // 24 for ValueTimestamp, 32 for java.sql.Timestamp
...@@ -310,9 +308,9 @@ public class DataType { ...@@ -310,9 +308,9 @@ public class DataType {
// compile (on Java 1.7). Can be replaced with // compile (on Java 1.7). Can be replaced with
// Types.TIMESTAMP_WITH_TIMEZONE once Java 1.8 is required. // Types.TIMESTAMP_WITH_TIMEZONE once Java 1.8 is required.
add(Value.TIMESTAMP_TZ, 2014, add(Value.TIMESTAMP_TZ, 2014,
createDate(ValueTimestampTimeZone.PRECISION, "TIMESTAMP_TZ", createDate(ValueTimestampTimeZone.MAXIMUM_PRECISION, ValueTimestampTimeZone.DEFAULT_PRECISION,
true, ValueTimestampTimeZone.DEFAULT_SCALE, ValueTimestampTimeZone.MAXIMUM_SCALE, "TIMESTAMP_TZ", true, ValueTimestampTimeZone.DEFAULT_SCALE,
ValueTimestampTimeZone.DISPLAY_SIZE), ValueTimestampTimeZone.MAXIMUM_SCALE),
new String[]{"TIMESTAMP WITH TIME ZONE"}, new String[]{"TIMESTAMP WITH TIME ZONE"},
// 26 for ValueTimestampUtc, 32 for java.sql.Timestamp // 26 for ValueTimestampUtc, 32 for java.sql.Timestamp
58 58
...@@ -466,17 +464,17 @@ public class DataType { ...@@ -466,17 +464,17 @@ public class DataType {
return dataType; return dataType;
} }
private static DataType createDate(int precision, String prefix, boolean supportsScale, int scale, int maxScale, private static DataType createDate(int maxPrecision, int precision, String prefix, boolean supportsScale, int scale,
int displaySize) { int maxScale) {
DataType dataType = new DataType(); DataType dataType = new DataType();
dataType.prefix = prefix + " '"; dataType.prefix = prefix + " '";
dataType.suffix = "'"; dataType.suffix = "'";
dataType.maxPrecision = precision; dataType.maxPrecision = maxPrecision;
dataType.supportsScale = supportsScale; dataType.supportsScale = supportsScale;
dataType.maxScale = maxScale; dataType.maxScale = maxScale;
dataType.defaultPrecision = precision; dataType.defaultPrecision = precision;
dataType.defaultScale = scale; dataType.defaultScale = scale;
dataType.defaultDisplaySize = displaySize; dataType.defaultDisplaySize = precision;
return dataType; return dataType;
} }
......
...@@ -19,15 +19,10 @@ import org.h2.util.DateTimeUtils; ...@@ -19,15 +19,10 @@ import org.h2.util.DateTimeUtils;
public class ValueDate extends Value { public class ValueDate extends Value {
/** /**
* The precision in digits. * The default precision and display size of the textual representation of a date.
*/
public static final int PRECISION = 8;
/**
* The display size of the textual representation of a date.
* Example: 2000-01-02 * Example: 2000-01-02
*/ */
public static final int DISPLAY_SIZE = 10; public static final int PRECISION = 10;
private final long dateValue; private final long dateValue;
...@@ -97,7 +92,7 @@ public class ValueDate extends Value { ...@@ -97,7 +92,7 @@ public class ValueDate extends Value {
@Override @Override
public String getString() { public String getString() {
StringBuilder buff = new StringBuilder(DISPLAY_SIZE); StringBuilder buff = new StringBuilder(PRECISION);
DateTimeUtils.appendDate(buff, dateValue); DateTimeUtils.appendDate(buff, dateValue);
return buff.toString(); return buff.toString();
} }
...@@ -114,7 +109,7 @@ public class ValueDate extends Value { ...@@ -114,7 +109,7 @@ public class ValueDate extends Value {
@Override @Override
public int getDisplaySize() { public int getDisplaySize() {
return DISPLAY_SIZE; return PRECISION;
} }
@Override @Override
......
...@@ -19,15 +19,16 @@ import org.h2.util.DateTimeUtils; ...@@ -19,15 +19,16 @@ import org.h2.util.DateTimeUtils;
public class ValueTime extends Value { public class ValueTime extends Value {
/** /**
* The precision in digits. * The default precision and display size of the textual representation of a time.
* Example: 10:00:00
*/ */
public static final int PRECISION = 9; public static final int DEFAULT_PRECISION = 8;
/** /**
* The display size of the textual representation of a time. * The maximum precision and display size of the textual representation of a time.
* Example: 10:00:00 * Example: 10:00:00.123456789
*/ */
static final int DISPLAY_SIZE = 8; public static final int MAXIMUM_PRECISION = 18;
/** /**
* The default scale for time. * The default scale for time.
...@@ -134,7 +135,7 @@ public class ValueTime extends Value { ...@@ -134,7 +135,7 @@ public class ValueTime extends Value {
@Override @Override
public String getString() { public String getString() {
StringBuilder buff = new StringBuilder(DISPLAY_SIZE); StringBuilder buff = new StringBuilder(MAXIMUM_PRECISION);
DateTimeUtils.appendTime(buff, nanos, false); DateTimeUtils.appendTime(buff, nanos, false);
return buff.toString(); return buff.toString();
} }
...@@ -146,12 +147,18 @@ public class ValueTime extends Value { ...@@ -146,12 +147,18 @@ public class ValueTime extends Value {
@Override @Override
public long getPrecision() { public long getPrecision() {
return PRECISION; return MAXIMUM_PRECISION;
} }
@Override @Override
public int getDisplaySize() { public int getDisplaySize() {
return DISPLAY_SIZE; return MAXIMUM_PRECISION;
}
@Override
public boolean checkPrecision(long precision) {
// TIME data type does not have precision parameter
return true;
} }
@Override @Override
......
...@@ -19,15 +19,16 @@ import org.h2.util.DateTimeUtils; ...@@ -19,15 +19,16 @@ import org.h2.util.DateTimeUtils;
public class ValueTimestamp extends Value { public class ValueTimestamp extends Value {
/** /**
* The precision in digits. * The default precision and display size of the textual representation of a timestamp.
* Example: 2001-01-01 23:59:59.123456
*/ */
public static final int PRECISION = 23; public static final int DEFAULT_PRECISION = 26;
/** /**
* The display size of the textual representation of a timestamp. * The maximum precision and display size of the textual representation of a timestamp.
* Example: 2001-01-01 23:59:59.000 * Example: 2001-01-01 23:59:59.123456789
*/ */
static final int DISPLAY_SIZE = 23; public static final int MAXIMUM_PRECISION = 29;
/** /**
* The default scale for timestamps. * The default scale for timestamps.
...@@ -179,7 +180,7 @@ public class ValueTimestamp extends Value { ...@@ -179,7 +180,7 @@ public class ValueTimestamp extends Value {
@Override @Override
public String getString() { public String getString() {
StringBuilder buff = new StringBuilder(DISPLAY_SIZE); StringBuilder buff = new StringBuilder(MAXIMUM_PRECISION);
DateTimeUtils.appendDate(buff, dateValue); DateTimeUtils.appendDate(buff, dateValue);
buff.append(' '); buff.append(' ');
DateTimeUtils.appendTime(buff, timeNanos, true); DateTimeUtils.appendTime(buff, timeNanos, true);
...@@ -193,7 +194,7 @@ public class ValueTimestamp extends Value { ...@@ -193,7 +194,7 @@ public class ValueTimestamp extends Value {
@Override @Override
public long getPrecision() { public long getPrecision() {
return PRECISION; return MAXIMUM_PRECISION;
} }
@Override @Override
...@@ -203,7 +204,13 @@ public class ValueTimestamp extends Value { ...@@ -203,7 +204,13 @@ public class ValueTimestamp extends Value {
@Override @Override
public int getDisplaySize() { public int getDisplaySize() {
return DISPLAY_SIZE; return MAXIMUM_PRECISION;
}
@Override
public boolean checkPrecision(long precision) {
// TIMESTAMP data type does not have precision parameter
return true;
} }
@Override @Override
......
...@@ -22,15 +22,16 @@ import org.h2.util.DateTimeUtils; ...@@ -22,15 +22,16 @@ import org.h2.util.DateTimeUtils;
public class ValueTimestampTimeZone extends Value { public class ValueTimestampTimeZone extends Value {
/** /**
* The precision in digits. * The default precision and display size of the textual representation of a timestamp.
* Example: 2001-01-01 23:59:59.123456+10:00
*/ */
public static final int PRECISION = 30; public static final int DEFAULT_PRECISION = 32;
/** /**
* The display size of the textual representation of a timestamp. Example: * The maximum precision and display size of the textual representation of a timestamp.
* 2001-01-01 23:59:59.000 +10:00 * Example: 2001-01-01 23:59:59.123456789+10:00
*/ */
public static final int DISPLAY_SIZE = 30; public static final int MAXIMUM_PRECISION = 35;
/** /**
* The default scale for timestamps. * The default scale for timestamps.
...@@ -182,7 +183,7 @@ public class ValueTimestampTimeZone extends Value { ...@@ -182,7 +183,7 @@ public class ValueTimestampTimeZone extends Value {
@Override @Override
public long getPrecision() { public long getPrecision() {
return PRECISION; return MAXIMUM_PRECISION;
} }
@Override @Override
...@@ -192,7 +193,13 @@ public class ValueTimestampTimeZone extends Value { ...@@ -192,7 +193,13 @@ public class ValueTimestampTimeZone extends Value {
@Override @Override
public int getDisplaySize() { public int getDisplaySize() {
return DISPLAY_SIZE; return MAXIMUM_PRECISION;
}
@Override
public boolean checkPrecision(long precision) {
// TIMESTAMP WITH TIME ZONE data type does not have precision parameter
return true;
} }
@Override @Override
......
...@@ -723,9 +723,9 @@ public class TestMetaData extends TestBase { ...@@ -723,9 +723,9 @@ public class TestMetaData extends TestBase {
"" + DatabaseMetaData.columnNullable, "", null, "" + DatabaseMetaData.columnNullable, "", null,
"" + numericType, "0", "12", "3", "YES" }, "" + numericType, "0", "12", "3", "YES" },
{ CATALOG, Constants.SCHEMA_MAIN, "TEST", "DATE_V", { CATALOG, Constants.SCHEMA_MAIN, "TEST", "DATE_V",
"" + Types.TIMESTAMP, "TIMESTAMP", "23", "23", "6", "" + Types.TIMESTAMP, "TIMESTAMP", "26", "26", "6",
"10", "" + DatabaseMetaData.columnNullable, "", null, "10", "" + DatabaseMetaData.columnNullable, "", null,
"" + Types.TIMESTAMP, "0", "23", "4", "YES" }, "" + Types.TIMESTAMP, "0", "26", "4", "YES" },
{ CATALOG, Constants.SCHEMA_MAIN, "TEST", "BLOB_V", { CATALOG, Constants.SCHEMA_MAIN, "TEST", "BLOB_V",
"" + Types.BLOB, "BLOB", "" + Integer.MAX_VALUE, "" + Types.BLOB, "BLOB", "" + Integer.MAX_VALUE,
"" + Integer.MAX_VALUE, "0", "10", "" + Integer.MAX_VALUE, "0", "10",
......
...@@ -1280,11 +1280,11 @@ public class TestResultSet extends TestBase { ...@@ -1280,11 +1280,11 @@ public class TestResultSet extends TestBase {
"TIMESTAMP '9999-12-31 23:59:59' VALUE FROM TEST ORDER BY ID"); "TIMESTAMP '9999-12-31 23:59:59' VALUE FROM TEST ORDER BY ID");
assertResultSetMeta(rs, 2, new String[] { "ID", "VALUE" }, assertResultSetMeta(rs, 2, new String[] { "ID", "VALUE" },
new int[] { Types.INTEGER, Types.TIMESTAMP }, new int[] { Types.INTEGER, Types.TIMESTAMP },
new int[] { 10, 23 }, new int[] { 0, 9 }); new int[] { 10, 29 }, new int[] { 0, 9 });
rs = stat.executeQuery("SELECT * FROM TEST ORDER BY ID"); rs = stat.executeQuery("SELECT * FROM TEST ORDER BY ID");
assertResultSetMeta(rs, 2, new String[] { "ID", "VALUE" }, assertResultSetMeta(rs, 2, new String[] { "ID", "VALUE" },
new int[] { Types.INTEGER, Types.TIMESTAMP }, new int[] { Types.INTEGER, Types.TIMESTAMP },
new int[] { 10, 23 }, new int[] { 0, 6 }); new int[] { 10, 26 }, new int[] { 0, 6 });
rs.next(); rs.next();
java.sql.Date date; java.sql.Date date;
java.sql.Time time; java.sql.Time time;
...@@ -1494,7 +1494,7 @@ public class TestResultSet extends TestBase { ...@@ -1494,7 +1494,7 @@ public class TestResultSet extends TestBase {
new String[] { "ID", "D", "T", "TS" }, new String[] { "ID", "D", "T", "TS" },
new int[] { Types.INTEGER, Types.DATE, new int[] { Types.INTEGER, Types.DATE,
Types.TIME, Types.TIMESTAMP }, Types.TIME, Types.TIMESTAMP },
new int[] { 10, 8, 9, 23 }, new int[] { 0, 0, 0, 9 }); new int[] { 10, 10, 8, 29 }, new int[] { 0, 0, 0, 9 });
rs.next(); rs.next();
assertEquals(0, rs.getInt(1)); assertEquals(0, rs.getInt(1));
......
...@@ -163,8 +163,9 @@ public class TestDate extends TestBase { ...@@ -163,8 +163,9 @@ public class TestDate extends TestBase {
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());
assertEquals(t1.getString().length(), t1.getDisplaySize()); // Literals return maximum precision
assertEquals(ValueTime.PRECISION, t1.getPrecision()); assertEquals(ValueTime.MAXIMUM_PRECISION, t1.getDisplaySize());
assertEquals(ValueTime.MAXIMUM_PRECISION, t1.getPrecision());
assertEquals("java.sql.Time", t1.getObject().getClass().getName()); assertEquals("java.sql.Time", t1.getObject().getClass().getName());
ValueTime t1b = ValueTime.parse("11:11:11"); ValueTime t1b = ValueTime.parse("11:11:11");
assertTrue(t1 == t1b); assertTrue(t1 == t1b);
...@@ -257,8 +258,9 @@ public class TestDate extends TestBase { ...@@ -257,8 +258,9 @@ public class TestDate extends TestBase {
assertEquals((int) ((dateValue >>> 32) ^ dateValue ^ assertEquals((int) ((dateValue >>> 32) ^ dateValue ^
(nanos >>> 32) ^ nanos), (nanos >>> 32) ^ nanos),
t1.hashCode()); t1.hashCode());
assertEquals(t1.getString().length(), t1.getDisplaySize()); // Literals return maximum precision
assertEquals(ValueTimestamp.PRECISION, t1.getPrecision()); assertEquals(ValueTimestamp.MAXIMUM_PRECISION, t1.getDisplaySize());
assertEquals(ValueTimestamp.MAXIMUM_PRECISION, t1.getPrecision());
assertEquals(9, t1.getScale()); assertEquals(9, t1.getScale());
assertEquals("java.sql.Timestamp", t1.getObject().getClass().getName()); assertEquals("java.sql.Timestamp", t1.getObject().getClass().getName());
ValueTimestamp t1b = ValueTimestamp.parse("2001-01-01 01:01:01.111"); ValueTimestamp t1b = ValueTimestamp.parse("2001-01-01 01:01:01.111");
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论