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

Parse fractional seconds precision as described in SQL standard

上级 e47fbaa9
...@@ -2446,9 +2446,10 @@ REAL ...@@ -2446,9 +2446,10 @@ REAL
" "
"Data Types","TIME Type"," "Data Types","TIME Type","
TIME [ WITHOUT TIME ZONE ] TIME [ ( precisionInt ) ] [ WITHOUT TIME ZONE ]
"," ","
The time data type. The format is hh:mm:ss[.nnnnnnnnn]. The time data type. The format is hh:mm:ss[.nnnnnnnnn].
If fractional seconds precision is specified it should be from 0 to 9, 0 is default.
Mapped to ""java.sql.Time"". When converted to a ""java.sql.Date"", the date is set to ""1970-01-01"". Mapped to ""java.sql.Time"". When converted to a ""java.sql.Date"", the date is set to ""1970-01-01"".
""java.time.LocalTime"" is also supported on Java 8 and later versions. ""java.time.LocalTime"" is also supported on Java 8 and later versions.
...@@ -2470,10 +2471,11 @@ DATE ...@@ -2470,10 +2471,11 @@ DATE
" "
"Data Types","TIMESTAMP Type"," "Data Types","TIMESTAMP Type","
{ TIMESTAMP [ WITHOUT TIME ZONE ] | DATETIME | SMALLDATETIME } { TIMESTAMP [ ( precisionInt ) ] [ WITHOUT TIME ZONE ] | DATETIME | SMALLDATETIME }
"," ","
The timestamp data type. The format is yyyy-MM-dd hh:mm:ss[.nnnnnnnnn]. The timestamp data type. The format is yyyy-MM-dd hh:mm:ss[.nnnnnnnnn].
Stored internally as a BCD-encoded date, and nanoseconds since midnight. Stored internally as a BCD-encoded date, and nanoseconds since midnight.
If fractional seconds precision is specified it should be from 0 to 9, 6 is default.
Mapped to ""java.sql.Timestamp"" (""java.util.Date"" may be used too). Mapped to ""java.sql.Timestamp"" (""java.util.Date"" may be used too).
""java.time.LocalDateTime"" is also supported on Java 8 and later versions. ""java.time.LocalDateTime"" is also supported on Java 8 and later versions.
...@@ -2482,10 +2484,11 @@ TIMESTAMP ...@@ -2482,10 +2484,11 @@ TIMESTAMP
" "
"Data Types","TIMESTAMP WITH TIME ZONE Type"," "Data Types","TIMESTAMP WITH TIME ZONE Type","
TIMESTAMP WITH TIME ZONE TIMESTAMP [ ( precisionInt ) ] WITH TIME ZONE
"," ","
The timestamp with time zone data type. The timestamp with time zone data type.
Stored internally as a BCD-encoded date, nanoseconds since midnight, and time zone offset in minutes. Stored internally as a BCD-encoded date, nanoseconds since midnight, and time zone offset in minutes.
If fractional seconds precision is specified it should be from 0 to 9, 6 is default.
Mapped to ""org.h2.api.TimestampWithTimeZone"". Mapped to ""org.h2.api.TimestampWithTimeZone"".
""java.time.OffsetDateTime"" and ""java.time.Instant"" are also supported on Java 8 and later versions. ""java.time.OffsetDateTime"" and ""java.time.Instant"" are also supported on Java 8 and later versions.
......
...@@ -4338,6 +4338,7 @@ public class Parser { ...@@ -4338,6 +4338,7 @@ public class Parser {
private Column parseColumnWithType(String columnName) { private Column parseColumnWithType(String columnName) {
String original = currentToken; String original = currentToken;
boolean regular = false; boolean regular = false;
int originalScale = -1;
if (readIf("LONG")) { if (readIf("LONG")) {
if (readIf("RAW")) { if (readIf("RAW")) {
original += " RAW"; original += " RAW";
...@@ -4351,12 +4352,30 @@ public class Parser { ...@@ -4351,12 +4352,30 @@ public class Parser {
original += " VARYING"; original += " VARYING";
} }
} else if (readIf("TIME")) { } else if (readIf("TIME")) {
if (readIf("(")) {
originalScale = readPositiveInt();
if (originalScale > ValueTime.MAXIMUM_SCALE) {
throw DbException.get(ErrorCode.INVALID_VALUE_SCALE_PRECISION, Integer.toString(originalScale));
}
read(")");
}
if (readIf("WITHOUT")) { if (readIf("WITHOUT")) {
read("TIME"); read("TIME");
read("ZONE"); read("ZONE");
original += " WITHOUT TIME ZONE"; original += " WITHOUT TIME ZONE";
} }
} else if (readIf("TIMESTAMP")) { } else if (readIf("TIMESTAMP")) {
if (readIf("(")) {
originalScale = readPositiveInt();
// Allow non-standard TIMESTAMP(..., ...) syntax
if (readIf(",")) {
originalScale = readPositiveInt();
}
if (originalScale > ValueTimestamp.MAXIMUM_SCALE) {
throw DbException.get(ErrorCode.INVALID_VALUE_SCALE_PRECISION, Integer.toString(originalScale));
}
read(")");
}
if (readIf("WITH")) { if (readIf("WITH")) {
read("TIME"); read("TIME");
read("ZONE"); read("ZONE");
...@@ -4410,7 +4429,35 @@ public class Parser { ...@@ -4410,7 +4429,35 @@ public class Parser {
: displaySize; : displaySize;
scale = scale == -1 ? dataType.defaultScale : scale; scale = scale == -1 ? dataType.defaultScale : scale;
if (dataType.supportsPrecision || dataType.supportsScale) { if (dataType.supportsPrecision || dataType.supportsScale) {
if (readIf("(")) { int t = dataType.type;
if (t == Value.TIME || t == Value.TIMESTAMP || t == Value.TIMESTAMP_TZ) {
if (originalScale >= 0) {
scale = originalScale;
precision = dataType.defaultPrecision;
switch (t) {
case Value.TIME:
if (original.equals("TIME WITHOUT TIME ZONE")) {
original = "TIME(" + originalScale + ") WITHOUT TIME ZONE";
} else {
original = original + '(' + originalScale + ')';
}
displaySize = ValueTime.getDisplaySize(originalScale);
break;
case Value.TIMESTAMP:
if (original.equals("TIMESTAMP WITHOUT TIME ZONE")) {
original = "TIMESTAMP(" + originalScale + ") WITHOUT TIME ZONE";
} else {
original = original + '(' + originalScale + ')';
}
displaySize = ValueTimestamp.getDisplaySize(originalScale);
break;
case Value.TIMESTAMP_TZ:
original = "TIMESTAMP(" + originalScale + ") WITH TIME ZONE";
displaySize = ValueTimestampTimeZone.getDisplaySize(originalScale);
break;
}
}
} else if (readIf("(")) {
if (!readIf("MAX")) { if (!readIf("MAX")) {
long p = readLong(); long p = readLong();
if (readIf("K")) { if (readIf("K")) {
...@@ -4431,14 +4478,7 @@ public class Parser { ...@@ -4431,14 +4478,7 @@ public class Parser {
scale = readInt(); scale = readInt();
original += ", " + scale; original += ", " + scale;
} else { } else {
// special case: TIMESTAMP(5) actually means scale = 0;
// TIMESTAMP(23, 5)
if (dataType.type == Value.TIMESTAMP) {
scale = MathUtils.convertLongToInt(p);
p = precision;
} else {
scale = 0;
}
} }
} }
precision = p; precision = p;
......
...@@ -282,20 +282,24 @@ public class DataType { ...@@ -282,20 +282,24 @@ public class DataType {
24 24
); );
add(Value.TIME, Types.TIME, add(Value.TIME, Types.TIME,
createDate(ValueTime.PRECISION, "TIME", 0, ValueTime.DISPLAY_SIZE), createDate(ValueTime.PRECISION, "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", 0, ValueDate.DISPLAY_SIZE), createDate(ValueDate.PRECISION, "DATE",
false, 0, 0, ValueDate.DISPLAY_SIZE),
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.PRECISION, "TIMESTAMP",
ValueTimestamp.DEFAULT_SCALE, ValueTimestamp.DISPLAY_SIZE), 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
...@@ -307,7 +311,8 @@ public class DataType { ...@@ -307,7 +311,8 @@ public class DataType {
// 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.PRECISION, "TIMESTAMP_TZ",
ValueTimestampTimeZone.DEFAULT_SCALE, ValueTimestampTimeZone.DISPLAY_SIZE), true, ValueTimestampTimeZone.DEFAULT_SCALE, ValueTimestampTimeZone.MAXIMUM_SCALE,
ValueTimestampTimeZone.DISPLAY_SIZE),
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
...@@ -461,14 +466,14 @@ public class DataType { ...@@ -461,14 +466,14 @@ public class DataType {
return dataType; return dataType;
} }
private static DataType createDate(int precision, String prefix, int scale, private static DataType createDate(int precision, String prefix, boolean supportsScale, int scale, int maxScale,
int displaySize) { int displaySize) {
DataType dataType = new DataType(); DataType dataType = new DataType();
dataType.prefix = prefix + " '"; dataType.prefix = prefix + " '";
dataType.suffix = "'"; dataType.suffix = "'";
dataType.maxPrecision = precision; dataType.maxPrecision = precision;
dataType.supportsScale = scale != 0; dataType.supportsScale = supportsScale;
dataType.maxScale = scale; dataType.maxScale = maxScale;
dataType.defaultPrecision = precision; dataType.defaultPrecision = precision;
dataType.defaultScale = scale; dataType.defaultScale = scale;
dataType.defaultDisplaySize = displaySize; dataType.defaultDisplaySize = displaySize;
......
...@@ -21,7 +21,7 @@ public class ValueTime extends Value { ...@@ -21,7 +21,7 @@ public class ValueTime extends Value {
/** /**
* The precision in digits. * The precision in digits.
*/ */
public static final int PRECISION = 6; public static final int PRECISION = 9;
/** /**
* The display size of the textual representation of a time. * The display size of the textual representation of a time.
...@@ -29,6 +29,26 @@ public class ValueTime extends Value { ...@@ -29,6 +29,26 @@ public class ValueTime extends Value {
*/ */
static final int DISPLAY_SIZE = 8; static final int DISPLAY_SIZE = 8;
/**
* The default scale for time.
*/
static final int DEFAULT_SCALE = 0;
/**
* The maximum scale for time.
*/
public static final int MAXIMUM_SCALE = 9;
/**
* Get display size for the specified scale.
*
* @param scale scale
* @return display size
*/
public static int getDisplaySize(int scale) {
return scale == 0 ? 8 : 9 + scale;
}
/** /**
* Nanoseconds since midnight * Nanoseconds since midnight
*/ */
......
...@@ -33,7 +33,22 @@ public class ValueTimestamp extends Value { ...@@ -33,7 +33,22 @@ public class ValueTimestamp extends Value {
/** /**
* The default scale for timestamps. * The default scale for timestamps.
*/ */
static final int DEFAULT_SCALE = 10; static final int DEFAULT_SCALE = 6;
/**
* The maximum scale for timestamps.
*/
public static final int MAXIMUM_SCALE = 9;
/**
* Get display size for the specified scale.
*
* @param scale scale
* @return display size
*/
public static int getDisplaySize(int scale) {
return scale == 0 ? 19 : 20 + scale;
}
/** /**
* A bit field with bits for the year, month, and day (see DateTimeUtils for * A bit field with bits for the year, month, and day (see DateTimeUtils for
...@@ -184,7 +199,7 @@ public class ValueTimestamp extends Value { ...@@ -184,7 +199,7 @@ public class ValueTimestamp extends Value {
@Override @Override
public int getScale() { public int getScale() {
return DEFAULT_SCALE; return MAXIMUM_SCALE;
} }
@Override @Override
...@@ -194,7 +209,7 @@ public class ValueTimestamp extends Value { ...@@ -194,7 +209,7 @@ public class ValueTimestamp extends Value {
@Override @Override
public Value convertScale(boolean onlyToSmallerScale, int targetScale) { public Value convertScale(boolean onlyToSmallerScale, int targetScale) {
if (targetScale >= DEFAULT_SCALE) { if (targetScale >= MAXIMUM_SCALE) {
return this; return this;
} }
if (targetScale < 0) { if (targetScale < 0) {
......
...@@ -36,7 +36,22 @@ public class ValueTimestampTimeZone extends Value { ...@@ -36,7 +36,22 @@ public class ValueTimestampTimeZone extends Value {
/** /**
* The default scale for timestamps. * The default scale for timestamps.
*/ */
static final int DEFAULT_SCALE = 10; static final int DEFAULT_SCALE = ValueTimestamp.DEFAULT_SCALE;
/**
* The default scale for timestamps.
*/
static final int MAXIMUM_SCALE = ValueTimestamp.MAXIMUM_SCALE;
/**
* Get display size for the specified scale.
*
* @param scale scale
* @return display size
*/
public static int getDisplaySize(int scale) {
return scale == 0 ? 25 : 26 + scale;
}
/** /**
* A bit field with bits for the year, month, and day (see DateTimeUtils for * A bit field with bits for the year, month, and day (see DateTimeUtils for
...@@ -173,7 +188,7 @@ public class ValueTimestampTimeZone extends Value { ...@@ -173,7 +188,7 @@ public class ValueTimestampTimeZone extends Value {
@Override @Override
public int getScale() { public int getScale() {
return DEFAULT_SCALE; return MAXIMUM_SCALE;
} }
@Override @Override
...@@ -183,7 +198,7 @@ public class ValueTimestampTimeZone extends Value { ...@@ -183,7 +198,7 @@ public class ValueTimestampTimeZone extends Value {
@Override @Override
public Value convertScale(boolean onlyToSmallerScale, int targetScale) { public Value convertScale(boolean onlyToSmallerScale, int targetScale) {
if (targetScale >= DEFAULT_SCALE) { if (targetScale >= MAXIMUM_SCALE) {
return this; return this;
} }
if (targetScale < 0) { if (targetScale < 0) {
......
...@@ -723,7 +723,7 @@ public class TestMetaData extends TestBase { ...@@ -723,7 +723,7 @@ 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", "10", "" + Types.TIMESTAMP, "TIMESTAMP", "23", "23", "6",
"10", "" + DatabaseMetaData.columnNullable, "", null, "10", "" + DatabaseMetaData.columnNullable, "", null,
"" + Types.TIMESTAMP, "0", "23", "4", "YES" }, "" + Types.TIMESTAMP, "0", "23", "4", "YES" },
{ CATALOG, Constants.SCHEMA_MAIN, "TEST", "BLOB_V", { CATALOG, Constants.SCHEMA_MAIN, "TEST", "BLOB_V",
......
...@@ -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, 10 }); new int[] { 10, 23 }, 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, 10 }); new int[] { 10, 23 }, new int[] { 0, 6 });
rs.next(); rs.next();
java.sql.Date date; java.sql.Date date;
java.sql.Time time; java.sql.Time time;
...@@ -1431,7 +1431,7 @@ public class TestResultSet extends TestBase { ...@@ -1431,7 +1431,7 @@ public class TestResultSet extends TestBase {
ResultSet rs; ResultSet rs;
stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, " + stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, " +
"D DATE, T TIME, TS TIMESTAMP)"); "D DATE, T TIME, TS TIMESTAMP(9))");
PreparedStatement prep = conn.prepareStatement( PreparedStatement prep = conn.prepareStatement(
"INSERT INTO TEST VALUES(?, ?, ?, ?)"); "INSERT INTO TEST VALUES(?, ?, ?, ?)");
Calendar regular = DateTimeUtils.createGregorianCalendar(); Calendar regular = DateTimeUtils.createGregorianCalendar();
...@@ -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, 6, 23 }, new int[] { 0, 0, 0, 10 }); new int[] { 10, 8, 9, 23 }, new int[] { 0, 0, 0, 9 });
rs.next(); rs.next();
assertEquals(0, rs.getInt(1)); assertEquals(0, rs.getInt(1));
......
...@@ -296,7 +296,7 @@ public class TestUpdatableResultSet extends TestBase { ...@@ -296,7 +296,7 @@ public class TestUpdatableResultSet extends TestBase {
ResultSet.CONCUR_UPDATABLE); ResultSet.CONCUR_UPDATABLE);
stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255), " stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255), "
+ "DEC DECIMAL(10,2), BOO BIT, BYE TINYINT, BIN BINARY(100), " + "DEC DECIMAL(10,2), BOO BIT, BYE TINYINT, BIN BINARY(100), "
+ "D DATE, T TIME, TS TIMESTAMP, DB DOUBLE, R REAL, L BIGINT, " + "D DATE, T TIME, TS TIMESTAMP(9), DB DOUBLE, R REAL, L BIGINT, "
+ "O_I INT, SH SMALLINT, CL CLOB, BL BLOB)"); + "O_I INT, SH SMALLINT, CL CLOB, BL BLOB)");
ResultSet rs = stat.executeQuery("SELECT * FROM TEST"); ResultSet rs = stat.executeQuery("SELECT * FROM TEST");
ResultSetMetaData meta = rs.getMetaData(); ResultSetMetaData meta = rs.getMetaData();
......
...@@ -23,6 +23,22 @@ SELECT COLUMN_NAME, DATA_TYPE, TYPE_NAME, COLUMN_TYPE FROM INFORMATION_SCHEMA.CO ...@@ -23,6 +23,22 @@ SELECT COLUMN_NAME, DATA_TYPE, TYPE_NAME, COLUMN_TYPE FROM INFORMATION_SCHEMA.CO
> T2 92 TIME TIME WITHOUT TIME ZONE > T2 92 TIME TIME WITHOUT TIME ZONE
> rows (ordered): 2 > rows (ordered): 2
ALTER TABLE TEST ADD (T3 TIME(0), T4 TIME(9) WITHOUT TIME ZONE);
> ok
SELECT COLUMN_NAME, DATA_TYPE, TYPE_NAME, COLUMN_TYPE, NUMERIC_SCALE FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'TEST' ORDER BY ORDINAL_POSITION;
> COLUMN_NAME DATA_TYPE TYPE_NAME COLUMN_TYPE NUMERIC_SCALE
> ----------- --------- --------- ------------------------- -------------
> T1 92 TIME TIME 0
> T2 92 TIME TIME WITHOUT TIME ZONE 0
> T3 92 TIME TIME(0) 0
> T4 92 TIME TIME(9) WITHOUT TIME ZONE 9
> rows (ordered): 4
ALTER TABLE TEST ADD T5 TIME(10);
> exception
DROP TABLE TEST; DROP TABLE TEST;
> ok > ok
......
...@@ -35,3 +35,21 @@ SELECT TIMESTAMP WITH TIME ZONE '2000-01-10 00:00:00 -02' AS A, ...@@ -35,3 +35,21 @@ SELECT TIMESTAMP WITH TIME ZONE '2000-01-10 00:00:00 -02' AS A,
> ------------------------ ------------------------ ------------------------ ------------------------ > ------------------------ ------------------------ ------------------------ ------------------------
> 2000-01-10 00:00:00.0-02 2000-01-10 00:00:00.0+02 2000-01-10 00:00:00.0+02 2000-01-10 00:00:00.0+09 > 2000-01-10 00:00:00.0-02 2000-01-10 00:00:00.0+02 2000-01-10 00:00:00.0+02 2000-01-10 00:00:00.0+09
> rows: 1 > rows: 1
CREATE TABLE TEST(T1 TIMESTAMP WITH TIME ZONE, T2 TIMESTAMP(0) WITH TIME ZONE, T3 TIMESTAMP(9) WITH TIME ZONE);
> ok
SELECT COLUMN_NAME, DATA_TYPE, TYPE_NAME, COLUMN_TYPE, NUMERIC_SCALE FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'TEST' ORDER BY ORDINAL_POSITION;
> COLUMN_NAME DATA_TYPE TYPE_NAME COLUMN_TYPE NUMERIC_SCALE
> ----------- --------- ------------------------ --------------------------- -------------
> T1 2014 TIMESTAMP WITH TIME ZONE TIMESTAMP WITH TIME ZONE 6
> T2 2014 TIMESTAMP WITH TIME ZONE TIMESTAMP(0) WITH TIME ZONE 0
> T3 2014 TIMESTAMP WITH TIME ZONE TIMESTAMP(9) WITH TIME ZONE 9
> rows (ordered): 3
ALTER TABLE TEST ADD T4 TIMESTAMP (10) WITH TIME ZONE;
> exception
DROP TABLE TEST;
> ok
...@@ -15,19 +15,26 @@ SELECT T1, T2, T1 = T2 FROM TEST; ...@@ -15,19 +15,26 @@ SELECT T1, T2, T1 = T2 FROM TEST;
> 2010-01-01 10:00:00.0 2010-01-01 10:00:00.0 TRUE > 2010-01-01 10:00:00.0 2010-01-01 10:00:00.0 TRUE
> rows: 1 > rows: 1
SELECT COLUMN_NAME, DATA_TYPE, TYPE_NAME, COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS ALTER TABLE TEST ADD (T3 TIMESTAMP(0), T4 TIMESTAMP(9) WITHOUT TIME ZONE);
SELECT COLUMN_NAME, DATA_TYPE, TYPE_NAME, COLUMN_TYPE, NUMERIC_SCALE FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'TEST' ORDER BY ORDINAL_POSITION; WHERE TABLE_NAME = 'TEST' ORDER BY ORDINAL_POSITION;
> COLUMN_NAME DATA_TYPE TYPE_NAME COLUMN_TYPE > COLUMN_NAME DATA_TYPE TYPE_NAME COLUMN_TYPE NUMERIC_SCALE
> ----------- --------- --------- --------------------------- > ----------- --------- --------- ------------------------------ -------------
> T1 93 TIMESTAMP TIMESTAMP > T1 93 TIMESTAMP TIMESTAMP 6
> T2 93 TIMESTAMP TIMESTAMP WITHOUT TIME ZONE > T2 93 TIMESTAMP TIMESTAMP WITHOUT TIME ZONE 6
> rows (ordered): 2 > T3 93 TIMESTAMP TIMESTAMP(0) 0
> T4 93 TIMESTAMP TIMESTAMP(9) WITHOUT TIME ZONE 9
> rows (ordered): 4
ALTER TABLE TEST ADD T5 TIMESTAMP(10);
> exception
DROP TABLE TEST; DROP TABLE TEST;
> ok > ok
-- Check that TIMESTAMP is allowed as a column name -- Check that TIMESTAMP is allowed as a column name
CREATE TABLE TEST(TIMESTAMP TIMESTAMP); CREATE TABLE TEST(TIMESTAMP TIMESTAMP(0));
> ok > ok
INSERT INTO TEST VALUES (TIMESTAMP '1999-12-31 08:00:00'); INSERT INTO TEST VALUES (TIMESTAMP '1999-12-31 08:00:00');
......
...@@ -6884,7 +6884,7 @@ DROP TABLE TEST; ...@@ -6884,7 +6884,7 @@ DROP TABLE TEST;
> ok > ok
--- data types (date and time) ---------------------------------------------------------------------------------------------- --- data types (date and time) ----------------------------------------------------------------------------------------------
CREATE MEMORY TABLE TEST(ID INT, XT TIME, XD DATE, XTS TIMESTAMP); CREATE MEMORY TABLE TEST(ID INT, XT TIME, XD DATE, XTS TIMESTAMP(9));
> ok > ok
INSERT INTO TEST VALUES(0, '0:0:0','1-2-3','2-3-4 0:0:0'); INSERT INTO TEST VALUES(0, '0:0:0','1-2-3','2-3-4 0:0:0');
...@@ -6941,7 +6941,7 @@ SCRIPT SIMPLE NOPASSWORDS NOSETTINGS; ...@@ -6941,7 +6941,7 @@ SCRIPT SIMPLE NOPASSWORDS NOSETTINGS;
> SCRIPT > SCRIPT
> ---------------------------------------------------------------------------------------------------------------------------------- > ----------------------------------------------------------------------------------------------------------------------------------
> -- 4 +/- SELECT COUNT(*) FROM PUBLIC.TEST; > -- 4 +/- SELECT COUNT(*) FROM PUBLIC.TEST;
> CREATE MEMORY TABLE PUBLIC.TEST( ID INT, XT TIME, XD DATE, XTS TIMESTAMP ); > CREATE MEMORY TABLE PUBLIC.TEST( ID INT, XT TIME, XD DATE, XTS TIMESTAMP(9) );
> CREATE USER IF NOT EXISTS SA PASSWORD '' ADMIN; > CREATE USER IF NOT EXISTS SA PASSWORD '' ADMIN;
> INSERT INTO PUBLIC.TEST(ID, XT, XD, XTS) VALUES(0, TIME '00:00:00', DATE '0001-02-03', TIMESTAMP '0002-03-04 00:00:00.0'); > INSERT INTO PUBLIC.TEST(ID, XT, XD, XTS) VALUES(0, TIME '00:00:00', DATE '0001-02-03', TIMESTAMP '0002-03-04 00:00:00.0');
> INSERT INTO PUBLIC.TEST(ID, XT, XD, XTS) VALUES(1, TIME '01:02:03', DATE '0004-05-06', TIMESTAMP '0007-08-09 00:01:02.0'); > INSERT INTO PUBLIC.TEST(ID, XT, XD, XTS) VALUES(1, TIME '01:02:03', DATE '0004-05-06', TIMESTAMP '0007-08-09 00:01:02.0');
......
...@@ -259,7 +259,7 @@ public class TestDate extends TestBase { ...@@ -259,7 +259,7 @@ public class TestDate extends TestBase {
t1.hashCode()); t1.hashCode());
assertEquals(t1.getString().length(), t1.getDisplaySize()); assertEquals(t1.getString().length(), t1.getDisplaySize());
assertEquals(ValueTimestamp.PRECISION, t1.getPrecision()); assertEquals(ValueTimestamp.PRECISION, t1.getPrecision());
assertEquals(10, 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");
assertTrue(t1 == t1b); assertTrue(t1 == t1b);
......
...@@ -52,7 +52,7 @@ public class TestTimeStampWithTimeZone extends TestBase { ...@@ -52,7 +52,7 @@ public class TestTimeStampWithTimeZone extends TestBase {
private void test1() throws SQLException { private void test1() throws SQLException {
Connection conn = getConnection(getTestName()); Connection conn = getConnection(getTestName());
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
stat.execute("create table test(id identity, t1 timestamp with time zone)"); stat.execute("create table test(id identity, t1 timestamp(9) with time zone)");
stat.execute("insert into test(t1) values('1970-01-01 12:00:00.00+00:15')"); stat.execute("insert into test(t1) values('1970-01-01 12:00:00.00+00:15')");
// verify NanosSinceMidnight is in local time and not UTC // verify NanosSinceMidnight is in local time and not UTC
stat.execute("insert into test(t1) values('2016-09-24 00:00:00.000000001+00:01')"); stat.execute("insert into test(t1) values('2016-09-24 00:00:00.000000001+00:01')");
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论