Unverified 提交 24c19ac5 authored 作者: Noel Grandin's avatar Noel Grandin 提交者: GitHub

Merge pull request #922 from katzyn/datetime

Parse and treat fractional seconds precision as described in SQL standard
...@@ -2448,9 +2448,10 @@ REAL ...@@ -2448,9 +2448,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.
...@@ -2472,10 +2473,11 @@ DATE ...@@ -2472,10 +2473,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.
...@@ -2484,10 +2486,11 @@ TIMESTAMP ...@@ -2484,10 +2486,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.
......
...@@ -4343,6 +4343,7 @@ public class Parser { ...@@ -4343,6 +4343,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";
...@@ -4356,12 +4357,30 @@ public class Parser { ...@@ -4356,12 +4357,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");
...@@ -4415,7 +4434,34 @@ public class Parser { ...@@ -4415,7 +4434,34 @@ 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;
switch (t) {
case Value.TIME:
if (original.equals("TIME WITHOUT TIME ZONE")) {
original = "TIME(" + originalScale + ") WITHOUT TIME ZONE";
} else {
original = original + '(' + originalScale + ')';
}
precision = 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 + ')';
}
precision = displaySize = ValueTimestamp.getDisplaySize(originalScale);
break;
case Value.TIMESTAMP_TZ:
original = "TIMESTAMP(" + originalScale + ") WITH TIME ZONE";
precision = 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")) {
...@@ -4436,14 +4482,7 @@ public class Parser { ...@@ -4436,14 +4482,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;
......
...@@ -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;
......
...@@ -69,6 +69,12 @@ public class DateTimeUtils { ...@@ -69,6 +69,12 @@ public class DateTimeUtils {
private static final int[] DAYS_OFFSET = { 0, 31, 61, 92, 122, 153, 184, private static final int[] DAYS_OFFSET = { 0, 31, 61, 92, 122, 153, 184,
214, 245, 275, 306, 337, 366 }; 214, 245, 275, 306, 337, 366 };
/**
* Multipliers for {@link #convertScale(long, int)}.
*/
private static final int[] CONVERT_SCALE_TABLE = { 1_000_000_000, 100_000_000,
10_000_000, 1_000_000, 100_000, 10_000, 1_000, 100, 10 };
/** /**
* The thread local. Can not override initialValue because this would result * The thread local. Can not override initialValue because this would result
* in an inner class, which would not be garbage collected in a web * in an inner class, which would not be garbage collected in a web
...@@ -1340,10 +1346,8 @@ public class DateTimeUtils { ...@@ -1340,10 +1346,8 @@ public class DateTimeUtils {
* *
* @param buff the target string builder * @param buff the target string builder
* @param nanos the time in nanoseconds * @param nanos the time in nanoseconds
* @param alwaysAddMillis whether to always add at least ".0"
*/ */
public static void appendTime(StringBuilder buff, long nanos, public static void appendTime(StringBuilder buff, long nanos) {
boolean alwaysAddMillis) {
if (nanos < 0) { if (nanos < 0) {
buff.append('-'); buff.append('-');
nanos = -nanos; nanos = -nanos;
...@@ -1367,7 +1371,7 @@ public class DateTimeUtils { ...@@ -1367,7 +1371,7 @@ public class DateTimeUtils {
StringUtils.appendZeroPadded(buff, 2, m); StringUtils.appendZeroPadded(buff, 2, m);
buff.append(':'); buff.append(':');
StringUtils.appendZeroPadded(buff, 2, s); StringUtils.appendZeroPadded(buff, 2, s);
if (alwaysAddMillis || ms > 0 || nanos > 0) { if (ms > 0 || nanos > 0) {
buff.append('.'); buff.append('.');
int start = buff.length(); int start = buff.length();
StringUtils.appendZeroPadded(buff, 3, ms); StringUtils.appendZeroPadded(buff, 3, ms);
...@@ -1415,10 +1419,10 @@ public class DateTimeUtils { ...@@ -1415,10 +1419,10 @@ 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);
appendTimeZone(buff, timeZoneOffsetMins); appendTimeZone(buff, timeZoneOffsetMins);
return buff.toString(); return buff.toString();
} }
...@@ -1448,4 +1452,23 @@ public class DateTimeUtils { ...@@ -1448,4 +1452,23 @@ public class DateTimeUtils {
return b.toString(); 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) {
if (scale >= 9) {
return nanosOfDay;
}
int m = CONVERT_SCALE_TABLE[scale];
long mod = nanosOfDay % m;
if (mod >= m >>> 1) {
nanosOfDay += m;
}
return nanosOfDay - mod;
}
} }
...@@ -282,20 +282,22 @@ public class DataType { ...@@ -282,20 +282,22 @@ 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.MAXIMUM_PRECISION, ValueTime.DEFAULT_PRECISION,
"TIME", true, ValueTime.DEFAULT_SCALE, ValueTime.MAXIMUM_SCALE),
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, ValueDate.PRECISION,
"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,
ValueTimestamp.DEFAULT_SCALE, ValueTimestamp.DISPLAY_SIZE), "TIMESTAMP", true, ValueTimestamp.DEFAULT_SCALE, ValueTimestamp.MAXIMUM_SCALE),
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
...@@ -306,8 +308,9 @@ public class DataType { ...@@ -306,8 +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,
ValueTimestampTimeZone.DEFAULT_SCALE, ValueTimestampTimeZone.DISPLAY_SIZE), "TIMESTAMP_TZ", true, ValueTimestampTimeZone.DEFAULT_SCALE,
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
...@@ -461,17 +464,17 @@ public class DataType { ...@@ -461,17 +464,17 @@ public class DataType {
return dataType; return dataType;
} }
private static DataType createDate(int precision, String prefix, int scale, 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 = 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 = 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,36 @@ import org.h2.util.DateTimeUtils; ...@@ -19,15 +19,36 @@ 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 = 6; 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
*/
public static final int MAXIMUM_PRECISION = 18;
/**
* The default scale for time.
*/
static final int DEFAULT_SCALE = 0;
/**
* The maximum scale for time.
*/ */
static final int DISPLAY_SIZE = 8; 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
...@@ -51,7 +72,7 @@ public class ValueTime extends Value { ...@@ -51,7 +72,7 @@ public class ValueTime extends Value {
if (!SysProperties.UNLIMITED_TIME_RANGE) { if (!SysProperties.UNLIMITED_TIME_RANGE) {
if (nanos < 0L || nanos >= 86400000000000L) { if (nanos < 0L || nanos >= 86400000000000L) {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
DateTimeUtils.appendTime(builder, nanos, false); DateTimeUtils.appendTime(builder, nanos);
throw DbException.get(ErrorCode.INVALID_DATETIME_CONSTANT_2, throw DbException.get(ErrorCode.INVALID_DATETIME_CONSTANT_2,
"TIME", builder.toString()); "TIME", builder.toString());
} }
...@@ -114,8 +135,8 @@ public class ValueTime extends Value { ...@@ -114,8 +135,8 @@ 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);
return buff.toString(); return buff.toString();
} }
...@@ -126,12 +147,37 @@ public class ValueTime extends Value { ...@@ -126,12 +147,37 @@ 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
public Value convertScale(boolean onlyToSmallerScale, int targetScale) {
if (targetScale >= MAXIMUM_SCALE) {
return this;
}
if (targetScale < 0) {
throw DbException.getInvalidValueException("scale", targetScale);
}
long n = nanos;
long n2 = DateTimeUtils.convertScale(n, targetScale);
if (n2 == n) {
return this;
}
if (n2 >= DateTimeUtils.NANOS_PER_DAY) {
n2 = DateTimeUtils.NANOS_PER_DAY - 1;
}
return fromNanos(n2);
} }
@Override @Override
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
*/ */
package org.h2.value; package org.h2.value;
import java.math.BigDecimal;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Timestamp; import java.sql.Timestamp;
...@@ -20,20 +19,36 @@ import org.h2.util.DateTimeUtils; ...@@ -20,20 +19,36 @@ 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.
*/ */
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
...@@ -165,10 +180,10 @@ public class ValueTimestamp extends Value { ...@@ -165,10 +180,10 @@ 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);
return buff.toString(); return buff.toString();
} }
...@@ -179,37 +194,44 @@ public class ValueTimestamp extends Value { ...@@ -179,37 +194,44 @@ public class ValueTimestamp extends Value {
@Override @Override
public long getPrecision() { public long getPrecision() {
return PRECISION; return MAXIMUM_PRECISION;
} }
@Override @Override
public int getScale() { public int getScale() {
return DEFAULT_SCALE; return MAXIMUM_SCALE;
} }
@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
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) {
throw DbException.getInvalidValueException("scale", targetScale); throw DbException.getInvalidValueException("scale", targetScale);
} }
long n = timeNanos; long n = timeNanos;
BigDecimal bd = BigDecimal.valueOf(n); long n2 = DateTimeUtils.convertScale(n, targetScale);
bd = bd.movePointLeft(9);
bd = ValueDecimal.setScale(bd, targetScale);
bd = bd.movePointRight(9);
long n2 = bd.longValue();
if (n2 == n) { if (n2 == n) {
return this; 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 @Override
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
*/ */
package org.h2.value; package org.h2.value;
import java.math.BigDecimal;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Timestamp; import java.sql.Timestamp;
...@@ -23,20 +22,36 @@ import org.h2.util.DateTimeUtils; ...@@ -23,20 +22,36 @@ 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.
*/ */
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
...@@ -168,37 +183,44 @@ public class ValueTimestampTimeZone extends Value { ...@@ -168,37 +183,44 @@ public class ValueTimestampTimeZone extends Value {
@Override @Override
public long getPrecision() { public long getPrecision() {
return PRECISION; return MAXIMUM_PRECISION;
} }
@Override @Override
public int getScale() { public int getScale() {
return DEFAULT_SCALE; return MAXIMUM_SCALE;
} }
@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
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) {
throw DbException.getInvalidValueException("scale", targetScale); throw DbException.getInvalidValueException("scale", targetScale);
} }
long n = timeNanos; long n = timeNanos;
BigDecimal bd = BigDecimal.valueOf(n); long n2 = DateTimeUtils.convertScale(n, targetScale);
bd = bd.movePointLeft(9);
bd = ValueDecimal.setScale(bd, targetScale);
bd = bd.movePointRight(9);
long n2 = bd.longValue();
if (n2 == n) { if (n2 == n) {
return this; 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 @Override
......
...@@ -84,26 +84,26 @@ public class TestDateStorage extends TestBase { ...@@ -84,26 +84,26 @@ public class TestDateStorage extends TestBase {
prep.execute(); prep.execute();
rs = stat.executeQuery("select * from ts order by x"); rs = stat.executeQuery("select * from ts order by x");
rs.next(); rs.next();
assertEquals("2010-03-14 02:15:00.0", assertEquals("2010-03-14 02:15:00",
rs.getString(1)); rs.getString(1));
assertEquals("2010-03-13 18:15:00.0", assertEquals("2010-03-13 18:15:00.0",
rs.getTimestamp(1, utcCalendar).toString()); rs.getTimestamp(1, utcCalendar).toString());
assertEquals("2010-03-14 03:15:00.0", assertEquals("2010-03-14 03:15:00.0",
rs.getTimestamp(1).toString()); rs.getTimestamp(1).toString());
assertEquals("2010-03-14 02:15:00.0", assertEquals("2010-03-14 02:15:00",
rs.getString("x")); rs.getString("x"));
assertEquals("2010-03-13 18:15:00.0", assertEquals("2010-03-13 18:15:00.0",
rs.getTimestamp("x", utcCalendar).toString()); rs.getTimestamp("x", utcCalendar).toString());
assertEquals("2010-03-14 03:15:00.0", assertEquals("2010-03-14 03:15:00.0",
rs.getTimestamp("x").toString()); rs.getTimestamp("x").toString());
rs.next(); rs.next();
assertEquals("2010-03-14 03:15:00.0", assertEquals("2010-03-14 03:15:00",
rs.getString(1)); rs.getString(1));
assertEquals("2010-03-13 19:15:00.0", assertEquals("2010-03-13 19:15:00.0",
rs.getTimestamp(1, utcCalendar).toString()); rs.getTimestamp(1, utcCalendar).toString());
assertEquals("2010-03-14 03:15:00.0", assertEquals("2010-03-14 03:15:00.0",
rs.getTimestamp(1).toString()); rs.getTimestamp(1).toString());
assertEquals("2010-03-14 03:15:00.0", assertEquals("2010-03-14 03:15:00",
rs.getString("x")); rs.getString("x"));
assertEquals("2010-03-13 19:15:00.0", assertEquals("2010-03-13 19:15:00.0",
rs.getTimestamp("x", utcCalendar).toString()); rs.getTimestamp("x", utcCalendar).toString());
......
...@@ -328,7 +328,7 @@ public class TestFunctions extends TestBase implements AggregateFunction { ...@@ -328,7 +328,7 @@ public class TestFunctions extends TestBase implements AggregateFunction {
rs = stat.executeQuery( rs = stat.executeQuery(
"call TO_CHAR_2(TIMESTAMP '2001-02-03 04:05:06', 'format')"); "call TO_CHAR_2(TIMESTAMP '2001-02-03 04:05:06', 'format')");
rs.next(); rs.next();
assertEquals("2001-02-03 04:05:06.0", rs.getString(1)); assertEquals("2001-02-03 04:05:06", rs.getString(1));
stat.execute("drop alias TO_CHAR_2"); stat.execute("drop alias TO_CHAR_2");
conn.close(); conn.close();
} }
......
...@@ -85,7 +85,7 @@ public class SupportedTypes { ...@@ -85,7 +85,7 @@ public class SupportedTypes {
s.myString = Long.toHexString(rand.nextLong()); s.myString = Long.toHexString(rand.nextLong());
s.myUtilDate = new java.util.Date(rand.nextLong()); s.myUtilDate = new java.util.Date(rand.nextLong());
s.mySqlDate = new java.sql.Date(rand.nextLong()); s.mySqlDate = new java.sql.Date(rand.nextLong());
s.mySqlTime = new java.sql.Time(rand.nextLong()); s.mySqlTime = new java.sql.Time(rand.nextLong() / 1_000 * 1_000);
s.mySqlTimestamp = new java.sql.Timestamp(rand.nextLong()); s.mySqlTimestamp = new java.sql.Timestamp(rand.nextLong());
return s; return s;
} }
......
...@@ -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", "10", "" + 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",
......
...@@ -1262,13 +1262,13 @@ public class TestResultSet extends TestBase { ...@@ -1262,13 +1262,13 @@ public class TestResultSet extends TestBase {
assertEquals("99999-12-23", rs.getString(1)); assertEquals("99999-12-23", rs.getString(1));
rs = stat.executeQuery("call timestamp '99999-12-23 01:02:03.000'"); rs = stat.executeQuery("call timestamp '99999-12-23 01:02:03.000'");
rs.next(); rs.next();
assertEquals("99999-12-23 01:02:03.0", rs.getString(1)); assertEquals("99999-12-23 01:02:03", rs.getString(1));
rs = stat.executeQuery("call date '-99999-12-23'"); rs = stat.executeQuery("call date '-99999-12-23'");
rs.next(); rs.next();
assertEquals("-99999-12-23", rs.getString(1)); assertEquals("-99999-12-23", rs.getString(1));
rs = stat.executeQuery("call timestamp '-99999-12-23 01:02:03.000'"); rs = stat.executeQuery("call timestamp '-99999-12-23 01:02:03.000'");
rs.next(); rs.next();
assertEquals("-99999-12-23 01:02:03.0", rs.getString(1)); assertEquals("-99999-12-23 01:02:03", rs.getString(1));
stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY,VALUE DATETIME)"); stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY,VALUE DATETIME)");
stat.execute("INSERT INTO TEST VALUES(1,DATE '2011-11-11')"); stat.execute("INSERT INTO TEST VALUES(1,DATE '2011-11-11')");
...@@ -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, 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, 10 }); 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;
...@@ -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, 10, 8, 29 }, 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
...@@ -41,3 +57,32 @@ SELECT TIME FROM TEST; ...@@ -41,3 +57,32 @@ SELECT TIME FROM TEST;
DROP TABLE TEST; DROP TABLE TEST;
> ok > ok
CREATE TABLE TEST(T TIME, T0 TIME(0), T1 TIME(1), T2 TIME(2), T3 TIME(3), T4 TIME(4), T5 TIME(5), T6 TIME(6),
T7 TIME(7), T8 TIME(8), T9 TIME(9));
> ok
INSERT INTO TEST VALUES ('08:00:00.123456789', '08:00:00.123456789', '08:00:00.123456789', '08:00:00.123456789',
'08:00:00.123456789', '08:00:00.123456789', '08:00:00.123456789', '08:00:00.123456789', '08:00:00.123456789',
'08:00:00.123456789', '08:00:00.123456789');
> update count: 1
SELECT * FROM TEST;
> T T0 T1 T2 T3 T4 T5 T6 T7 T8 T9
> -------- -------- ---------- ----------- ------------ ------------- -------------- --------------- ---------------- ----------------- ------------------
> 08:00:00 08:00:00 08:00:00.1 08:00:00.12 08:00:00.123 08:00:00.1235 08:00:00.12346 08:00:00.123457 08:00:00.1234568 08:00:00.12345679 08:00:00.123456789
> rows: 1
DELETE FROM TEST;
> update count: 1
INSERT INTO TEST(T0) VALUES ('23:59:59.999999999');
> update count: 1
SELECT T0 FROM TEST;
> T0
> ------------------
> 23:59:59.999999999
DROP TABLE TEST;
> ok
...@@ -11,8 +11,8 @@ INSERT INTO tab_with_timezone(x) VALUES ('2017-01-01'); ...@@ -11,8 +11,8 @@ INSERT INTO tab_with_timezone(x) VALUES ('2017-01-01');
SELECT "Query".* FROM (select * from tab_with_timezone where x > '2016-01-01') AS "Query"; SELECT "Query".* FROM (select * from tab_with_timezone where x > '2016-01-01') AS "Query";
> X > X
> ------------------------ > ----------------------
> 2017-01-01 00:00:00.0+00 > 2017-01-01 00:00:00+00
DELETE FROM tab_with_timezone; DELETE FROM tab_with_timezone;
> update count: 1 > update count: 1
...@@ -22,16 +22,78 @@ INSERT INTO tab_with_timezone VALUES ('2018-03-25 01:59:00 Europe/Berlin'), ('20 ...@@ -22,16 +22,78 @@ INSERT INTO tab_with_timezone VALUES ('2018-03-25 01:59:00 Europe/Berlin'), ('20
SELECT * FROM tab_with_timezone ORDER BY X; SELECT * FROM tab_with_timezone ORDER BY X;
> X > X
> ------------------------ > ----------------------
> 2018-03-25 01:59:00.0+01 > 2018-03-25 01:59:00+01
> 2018-03-25 03:00:00.0+02 > 2018-03-25 03:00:00+02
> rows (ordered): 2 > rows (ordered): 2
SELECT TIMESTAMP WITH TIME ZONE '2000-01-10 00:00:00 -02' AS A, SELECT TIMESTAMP WITH TIME ZONE '2000-01-10 00:00:00 -02' AS A,
TIMESTAMP WITH TIME ZONE '2000-01-10 00:00:00.000000000 +02:00' AS B, TIMESTAMP WITH TIME ZONE '2000-01-10 00:00:00.000000000 +02:00' AS B,
TIMESTAMP WITH TIME ZONE '2000-01-10 00:00:00.000000000+02:00' AS C, TIMESTAMP WITH TIME ZONE '2000-01-10 00:00:00.000000000+02:00' AS C,
TIMESTAMP WITH TIME ZONE '2000-01-10T00:00:00.000000000+09:00[Asia/Tokyo]' AS D; TIMESTAMP WITH TIME ZONE '2000-01-10T00:00:00.000000000+09:00[Asia/Tokyo]' AS D;
> A B C D > A B C D
> ------------------------ ------------------------ ------------------------ ------------------------ > ---------------------- ---------------------- ---------------------- ----------------------
> 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-02 2000-01-10 00:00:00+02 2000-01-10 00:00:00+02 2000-01-10 00:00:00+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
CREATE TABLE TEST(T TIMESTAMP WITH TIME ZONE, T0 TIMESTAMP(0) WITH TIME ZONE, T1 TIMESTAMP(1) WITH TIME ZONE,
T2 TIMESTAMP(2) WITH TIME ZONE, T3 TIMESTAMP(3) WITH TIME ZONE, T4 TIMESTAMP(4) WITH TIME ZONE,
T5 TIMESTAMP(5) WITH TIME ZONE, T6 TIMESTAMP(6) WITH TIME ZONE, T7 TIMESTAMP(7) WITH TIME ZONE,
T8 TIMESTAMP(8) WITH TIME ZONE, T9 TIMESTAMP(9) WITH TIME ZONE);
> ok
INSERT INTO TEST VALUES ('2000-01-01 08:00:00.123456789Z', '2000-01-01 08:00:00.123456789Z',
'2000-01-01 08:00:00.123456789Z', '2000-01-01 08:00:00.123456789Z', '2000-01-01 08:00:00.123456789Z',
'2000-01-01 08:00:00.123456789Z', '2000-01-01 08:00:00.123456789Z', '2000-01-01 08:00:00.123456789Z',
'2000-01-01 08:00:00.123456789Z', '2000-01-01 08:00:00.123456789Z', '2000-01-01 08:00:00.123456789Z');
> update count: 1
SELECT T, T0, T1, T2 FROM TEST;
> T T0 T1 T2
> ----------------------------- ---------------------- ------------------------ -------------------------
> 2000-01-01 08:00:00.123457+00 2000-01-01 08:00:00+00 2000-01-01 08:00:00.1+00 2000-01-01 08:00:00.12+00
> rows: 1
SELECT T3, T4, T5, T6 FROM TEST;
> T3 T4 T5 T6
> -------------------------- --------------------------- ---------------------------- -----------------------------
> 2000-01-01 08:00:00.123+00 2000-01-01 08:00:00.1235+00 2000-01-01 08:00:00.12346+00 2000-01-01 08:00:00.123457+00
> rows: 1
SELECT T7, T8, T9 FROM TEST;
> T7 T8 T9
> ------------------------------ ------------------------------- --------------------------------
> 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+00
DROP TABLE TEST;
> ok
...@@ -10,24 +10,31 @@ INSERT INTO TEST(T1, T2) VALUES (TIMESTAMP '2010-01-01 10:00:00', TIMESTAMP WITH ...@@ -10,24 +10,31 @@ INSERT INTO TEST(T1, T2) VALUES (TIMESTAMP '2010-01-01 10:00:00', TIMESTAMP WITH
> update count: 1 > update count: 1
SELECT T1, T2, T1 = T2 FROM TEST; SELECT T1, T2, T1 = T2 FROM TEST;
> T1 T2 T1 = T2 > T1 T2 T1 = T2
> --------------------- --------------------- ------- > ------------------- ------------------- -------
> 2010-01-01 10:00:00.0 2010-01-01 10:00:00.0 TRUE > 2010-01-01 10:00:00 2010-01-01 10:00:00 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');
...@@ -35,9 +42,51 @@ INSERT INTO TEST VALUES (TIMESTAMP '1999-12-31 08:00:00'); ...@@ -35,9 +42,51 @@ INSERT INTO TEST VALUES (TIMESTAMP '1999-12-31 08:00:00');
SELECT TIMESTAMP FROM TEST; SELECT TIMESTAMP FROM TEST;
> TIMESTAMP > TIMESTAMP
> --------------------- > -------------------
> 1999-12-31 08:00:00.0 > 1999-12-31 08:00:00
> rows: 1
DROP TABLE TEST;
> ok
CREATE TABLE TEST(T TIMESTAMP, T0 TIMESTAMP(0), T1 TIMESTAMP(1), T2 TIMESTAMP(2), T3 TIMESTAMP(3), T4 TIMESTAMP(4),
T5 TIMESTAMP(5), T6 TIMESTAMP(6), T7 TIMESTAMP(7), T8 TIMESTAMP(8), T9 TIMESTAMP(9));
> ok
INSERT INTO TEST VALUES ('2000-01-01 08:00:00.123456789', '2000-01-01 08:00:00.123456789',
'2000-01-01 08:00:00.123456789', '2000-01-01 08:00:00.123456789', '2000-01-01 08:00:00.123456789',
'2000-01-01 08:00:00.123456789', '2000-01-01 08:00:00.123456789', '2000-01-01 08:00:00.123456789',
'2000-01-01 08:00:00.123456789', '2000-01-01 08:00:00.123456789', '2000-01-01 08:00:00.123456789');
> update count: 1
SELECT T, T0, T1, T2 FROM TEST;
> T T0 T1 T2
> -------------------------- ------------------- --------------------- ----------------------
> 2000-01-01 08:00:00.123457 2000-01-01 08:00:00 2000-01-01 08:00:00.1 2000-01-01 08:00:00.12
> rows: 1
SELECT T3, T4, T5, T6 FROM TEST;
> T3 T4 T5 T6
> ----------------------- ------------------------ ------------------------- --------------------------
> 2000-01-01 08:00:00.123 2000-01-01 08:00:00.1235 2000-01-01 08:00:00.12346 2000-01-01 08:00:00.123457
> rows: 1
SELECT T7, T8, T9 FROM TEST;
> T7 T8 T9
> --------------------------- ---------------------------- -----------------------------
> 2000-01-01 08:00:00.1234568 2000-01-01 08:00:00.12345679 2000-01-01 08:00:00.123456789
> rows: 1 > 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
DROP TABLE TEST; DROP TABLE TEST;
> ok > ok
...@@ -560,29 +560,29 @@ insert into test values ('2000-01-20 20:00:00'), ('2000-01-20 20:00:00'), ('2000 ...@@ -560,29 +560,29 @@ insert into test values ('2000-01-20 20:00:00'), ('2000-01-20 20:00:00'), ('2000
select median(v) from test; select median(v) from test;
> MEDIAN(V) > MEDIAN(V)
> --------------------- > -------------------
> 2000-01-20 20:00:00.0 > 2000-01-20 20:00:00
insert into test values (null); insert into test values (null);
> update count: 1 > update count: 1
select median(v) from test; select median(v) from test;
> MEDIAN(V) > MEDIAN(V)
> --------------------- > -------------------
> 2000-01-20 20:00:00.0 > 2000-01-20 20:00:00
select median(distinct v) from test; select median(distinct v) from test;
> MEDIAN(DISTINCT V) > MEDIAN(DISTINCT V)
> --------------------- > -------------------
> 2000-01-15 15:00:00.0 > 2000-01-15 15:00:00
insert into test values ('2000-01-10 10:00:00'); insert into test values ('2000-01-10 10:00:00');
> update count: 1 > update count: 1
select median(v) from test; select median(v) from test;
> MEDIAN(V) > MEDIAN(V)
> --------------------- > -------------------
> 2000-01-15 15:00:00.0 > 2000-01-15 15:00:00
delete from test; delete from test;
> update count: 5 > update count: 5
...@@ -592,8 +592,8 @@ insert into test values ('2000-01-20 20:00:00'), ('2000-01-21 20:00:00'); ...@@ -592,8 +592,8 @@ insert into test values ('2000-01-20 20:00:00'), ('2000-01-21 20:00:00');
select median(v) from test; select median(v) from test;
> MEDIAN(V) > MEDIAN(V)
> --------------------- > -------------------
> 2000-01-21 08:00:00.0 > 2000-01-21 08:00:00
drop table test; drop table test;
> ok > ok
...@@ -606,29 +606,29 @@ insert into test values ('2000-01-20 20:00:00+04'), ('2000-01-20 20:00:00+04'), ...@@ -606,29 +606,29 @@ insert into test values ('2000-01-20 20:00:00+04'), ('2000-01-20 20:00:00+04'),
select median(v) from test; select median(v) from test;
> MEDIAN(V) > MEDIAN(V)
> ------------------------ > ----------------------
> 2000-01-20 20:00:00.0+04 > 2000-01-20 20:00:00+04
insert into test values (null); insert into test values (null);
> update count: 1 > update count: 1
select median(v) from test; select median(v) from test;
> MEDIAN(V) > MEDIAN(V)
> ------------------------ > ----------------------
> 2000-01-20 20:00:00.0+04 > 2000-01-20 20:00:00+04
select median(distinct v) from test; select median(distinct v) from test;
> MEDIAN(DISTINCT V) > MEDIAN(DISTINCT V)
> ------------------------ > ----------------------
> 2000-01-15 15:00:00.0+03 > 2000-01-15 15:00:00+03
insert into test values ('2000-01-10 10:00:00+02'); insert into test values ('2000-01-10 10:00:00+02');
> update count: 1 > update count: 1
select median(v) from test; select median(v) from test;
> MEDIAN(V) > MEDIAN(V)
> ------------------------ > ----------------------
> 2000-01-15 15:00:00.0+03 > 2000-01-15 15:00:00+03
delete from test; delete from test;
> update count: 5 > update count: 5
...@@ -638,8 +638,8 @@ insert into test values ('2000-01-20 20:00:00+10:15'), ('2000-01-21 20:00:00-09' ...@@ -638,8 +638,8 @@ insert into test values ('2000-01-20 20:00:00+10:15'), ('2000-01-21 20:00:00-09'
select median(v) from test; select median(v) from test;
> MEDIAN(V) > MEDIAN(V)
> --------------------------- > -------------------------
> 2000-01-21 08:00:30.0+00:37 > 2000-01-21 08:00:30+00:37
drop table test; drop table test;
> ok > ok
......
...@@ -6,22 +6,22 @@ ...@@ -6,22 +6,22 @@
-- 01-Aug-03 + 3 months = 01-Nov-03 -- 01-Aug-03 + 3 months = 01-Nov-03
SELECT ADD_MONTHS('2003-08-01', 3) AS R; SELECT ADD_MONTHS('2003-08-01', 3) AS R;
> R > R
> --------------------- > -------------------
> 2003-11-01 00:00:00.0 > 2003-11-01 00:00:00
> rows: 1 > rows: 1
-- 31-Jan-03 + 1 month = 28-Feb-2003 -- 31-Jan-03 + 1 month = 28-Feb-2003
SELECT ADD_MONTHS('2003-01-31', 1) AS R; SELECT ADD_MONTHS('2003-01-31', 1) AS R;
> R > R
> --------------------- > -------------------
> 2003-02-28 00:00:00.0 > 2003-02-28 00:00:00
> rows: 1 > rows: 1
-- 21-Aug-2003 - 3 months = 21-May-2003 -- 21-Aug-2003 - 3 months = 21-May-2003
SELECT ADD_MONTHS('2003-08-21', -3) AS R; SELECT ADD_MONTHS('2003-08-21', -3) AS R;
> R > R
> --------------------- > -------------------
> 2003-05-21 00:00:00.0 > 2003-05-21 00:00:00
> rows: 1 > rows: 1
-- 21-Aug-2003 00:00:00.333 - 3 months = 21-May-2003 00:00:00.333 -- 21-Aug-2003 00:00:00.333 - 3 months = 21-May-2003 00:00:00.333
......
...@@ -16,8 +16,8 @@ select length(curtime())>=8 c1, length(current_time())>=8 c2, substring(curtime( ...@@ -16,8 +16,8 @@ select length(curtime())>=8 c1, length(current_time())>=8 c2, substring(curtime(
> rows: 1 > rows: 1
select length(now())>20 c1, length(current_timestamp())>20 c2, length(now(0))>20 c3, length(now(2))>20 c4, substring(now(5), 20, 1) c5 from test; select length(now())>20 c1, length(current_timestamp())>18 c2, length(now(0))>18 c3, length(now(2))>18 c4 from test;
> C1 C2 C3 C4 C5 > C1 C2 C3 C4
> ---- ---- ---- ---- -- > ---- ---- ---- ----
> TRUE TRUE TRUE TRUE . > TRUE TRUE TRUE TRUE
> rows: 1 > rows: 1
...@@ -32,68 +32,68 @@ insert into test values(date '2001-01-01', time '01:00:00', timestamp '2010-01-0 ...@@ -32,68 +32,68 @@ insert into test values(date '2001-01-01', time '01:00:00', timestamp '2010-01-0
select ts + t x from test; select ts + t x from test;
> X > X
> --------------------- > -------------------
> 2010-01-01 01:00:00.0 > 2010-01-01 01:00:00
> rows: 1 > rows: 1
select ts + t + t - t x from test; select ts + t + t - t x from test;
> X > X
> --------------------- > -------------------
> 2010-01-01 01:00:00.0 > 2010-01-01 01:00:00
> rows: 1 > rows: 1
select ts + t * 0.5 x from test; select ts + t * 0.5 x from test;
> X > X
> --------------------- > -------------------
> 2010-01-01 00:30:00.0 > 2010-01-01 00:30:00
> rows: 1 > rows: 1
select ts + 0.5 x from test; select ts + 0.5 x from test;
> X > X
> --------------------- > -------------------
> 2010-01-01 12:00:00.0 > 2010-01-01 12:00:00
> rows: 1 > rows: 1
select ts - 1.5 x from test; select ts - 1.5 x from test;
> X > X
> --------------------- > -------------------
> 2009-12-30 12:00:00.0 > 2009-12-30 12:00:00
> rows: 1 > rows: 1
select ts + 0.5 * t + t - t x from test; select ts + 0.5 * t + t - t x from test;
> X > X
> --------------------- > -------------------
> 2010-01-01 00:30:00.0 > 2010-01-01 00:30:00
> rows: 1 > rows: 1
select ts + t / 0.5 x from test; select ts + t / 0.5 x from test;
> X > X
> --------------------- > -------------------
> 2010-01-01 02:00:00.0 > 2010-01-01 02:00:00
> rows: 1 > rows: 1
select d + t, t + d - t x from test; select d + t, t + d - t x from test;
> T + D X > T + D X
> --------------------- --------------------- > ------------------- -------------------
> 2001-01-01 01:00:00.0 2001-01-01 00:00:00.0 > 2001-01-01 01:00:00 2001-01-01 00:00:00
> rows: 1 > rows: 1
select 1 + d + 1, d - 1, 2 + ts + 2, ts - 2 from test; select 1 + d + 1, d - 1, 2 + ts + 2, ts - 2 from test;
> DATEADD('DAY', 1, DATEADD('DAY', 1, D)) DATEADD('DAY', -1, D) DATEADD('DAY', 2, DATEADD('DAY', 2, TS)) DATEADD('DAY', -2, TS) > DATEADD('DAY', 1, DATEADD('DAY', 1, D)) DATEADD('DAY', -1, D) DATEADD('DAY', 2, DATEADD('DAY', 2, TS)) DATEADD('DAY', -2, TS)
> --------------------------------------- --------------------- ---------------------------------------- ---------------------- > --------------------------------------- --------------------- ---------------------------------------- ----------------------
> 2001-01-03 2000-12-31 2010-01-05 00:00:00.0 2009-12-30 00:00:00.0 > 2001-01-03 2000-12-31 2010-01-05 00:00:00 2009-12-30 00:00:00
> rows: 1 > rows: 1
select 1 + d + t + 1 from test; select 1 + d + t + 1 from test;
> DATEADD('DAY', 1, (T + DATEADD('DAY', 1, D))) > DATEADD('DAY', 1, (T + DATEADD('DAY', 1, D)))
> --------------------------------------------- > ---------------------------------------------
> 2001-01-03 01:00:00.0 > 2001-01-03 01:00:00
> rows: 1 > rows: 1
select ts - t - 2 from test; select ts - t - 2 from test;
> DATEADD('DAY', -2, (TS - T)) > DATEADD('DAY', -2, (TS - T))
> ---------------------------- > ----------------------------
> 2009-12-29 23:00:00.0 > 2009-12-29 23:00:00
> rows: 1 > rows: 1
drop table test; drop table test;
...@@ -118,9 +118,9 @@ SELECT DATEADD('NANOSECOND', 1, TIME '10:00:01'), DATEADD('NS', 1, TIMESTAMP '20 ...@@ -118,9 +118,9 @@ SELECT DATEADD('NANOSECOND', 1, TIME '10:00:01'), DATEADD('NS', 1, TIMESTAMP '20
> rows: 1 > rows: 1
SELECT DATEADD('HOUR', 1, DATE '2010-01-20'); SELECT DATEADD('HOUR', 1, DATE '2010-01-20');
> TIMESTAMP '2010-01-20 01:00:00.0' > TIMESTAMP '2010-01-20 01:00:00'
> --------------------------------- > -------------------------------
> 2010-01-20 01:00:00.0 > 2010-01-20 01:00:00
> rows: 1 > rows: 1
SELECT DATEADD('MINUTE', 30, TIME '12:30:55'); SELECT DATEADD('MINUTE', 30, TIME '12:30:55');
...@@ -152,14 +152,14 @@ SELECT TIMESTAMPADD('DAY', 10, TIMESTAMP '2000-01-05 15:00:30.123456789'); ...@@ -152,14 +152,14 @@ SELECT TIMESTAMPADD('DAY', 10, TIMESTAMP '2000-01-05 15:00:30.123456789');
SELECT TIMESTAMPADD('TIMEZONE_HOUR', 1, TIMESTAMP WITH TIME ZONE '2010-01-01 10:00:00+07:30') AS T; SELECT TIMESTAMPADD('TIMEZONE_HOUR', 1, TIMESTAMP WITH TIME ZONE '2010-01-01 10:00:00+07:30') AS T;
> T > T
> --------------------------- > -------------------------
> 2010-01-01 10:00:00.0+08:30 > 2010-01-01 10:00:00+08:30
> rows: 1 > rows: 1
SELECT TIMESTAMPADD('TIMEZONE_MINUTE', -45, TIMESTAMP WITH TIME ZONE '2010-01-01 10:00:00+07:30') AS T; SELECT TIMESTAMPADD('TIMEZONE_MINUTE', -45, TIMESTAMP WITH TIME ZONE '2010-01-01 10:00:00+07:30') AS T;
> T > T
> --------------------------- > -------------------------
> 2010-01-01 10:00:00.0+06:45 > 2010-01-01 10:00:00+06:45
> rows: 1 > rows: 1
SELECT DATEADD(HOUR, 1, TIME '23:00:00') AS T; SELECT DATEADD(HOUR, 1, TIME '23:00:00') AS T;
......
...@@ -4,14 +4,14 @@ ...@@ -4,14 +4,14 @@
-- --
CALL PARSEDATETIME('3. Februar 2001', 'd. MMMM yyyy', 'de'); CALL PARSEDATETIME('3. Februar 2001', 'd. MMMM yyyy', 'de');
> TIMESTAMP '2001-02-03 00:00:00.0' > TIMESTAMP '2001-02-03 00:00:00'
> --------------------------------- > -------------------------------
> 2001-02-03 00:00:00.0 > 2001-02-03 00:00:00
> rows: 1 > rows: 1
CALL PARSEDATETIME('02/03/2001 04:05:06', 'MM/dd/yyyy HH:mm:ss'); CALL PARSEDATETIME('02/03/2001 04:05:06', 'MM/dd/yyyy HH:mm:ss');
> TIMESTAMP '2001-02-03 04:05:06.0' > TIMESTAMP '2001-02-03 04:05:06'
> --------------------------------- > -------------------------------
> 2001-02-03 04:05:06.0 > 2001-02-03 04:05:06
> rows: 1 > rows: 1
...@@ -5,24 +5,24 @@ ...@@ -5,24 +5,24 @@
select trunc('2015-05-29 15:00:00') R; select trunc('2015-05-29 15:00:00') R;
> R > R
> --------------------- > -------------------
> 2015-05-29 00:00:00.0 > 2015-05-29 00:00:00
> rows: 1 > rows: 1
select trunc('2015-05-29') R; select trunc('2015-05-29') R;
> R > R
> --------------------- > -------------------
> 2015-05-29 00:00:00.0 > 2015-05-29 00:00:00
> rows: 1 > rows: 1
select trunc(timestamp '2000-01-01 10:20:30.0') R; select trunc(timestamp '2000-01-01 10:20:30.0') R;
> R > R
> --------------------- > -------------------
> 2000-01-01 00:00:00.0 > 2000-01-01 00:00:00
> rows: 1 > rows: 1
select trunc(timestamp '2001-01-01 14:00:00.0') R; select trunc(timestamp '2001-01-01 14:00:00.0') R;
> R > R
> --------------------- > -------------------
> 2001-01-01 00:00:00.0 > 2001-01-01 00:00:00
> rows: 1 > rows: 1
...@@ -1330,10 +1330,10 @@ INSERT INTO p VALUES('-1-01-01'), ('0-01-01'), ('0001-01-01'); ...@@ -1330,10 +1330,10 @@ INSERT INTO p VALUES('-1-01-01'), ('0-01-01'), ('0001-01-01');
select d, year(d), extract(year from d), cast(d as timestamp) from p; select d, year(d), extract(year from d), cast(d as timestamp) from p;
> D YEAR(D) EXTRACT(YEAR FROM D) CAST(D AS TIMESTAMP) > D YEAR(D) EXTRACT(YEAR FROM D) CAST(D AS TIMESTAMP)
> ---------- ------- -------------------- --------------------- > ---------- ------- -------------------- --------------------
> -1-01-01 -1 -1 -1-01-01 00:00:00.0 > -1-01-01 -1 -1 -1-01-01 00:00:00
> 0-01-01 0 0 0-01-01 00:00:00.0 > 0-01-01 0 0 0-01-01 00:00:00
> 0001-01-01 1 1 0001-01-01 00:00:00.0 > 0001-01-01 1 1 0001-01-01 00:00:00
> rows: 3 > rows: 3
drop table p; drop table p;
...@@ -2490,14 +2490,14 @@ insert into test values(1, '1999-12-01 23:59:00.000'); ...@@ -2490,14 +2490,14 @@ insert into test values(1, '1999-12-01 23:59:00.000');
select * from test where d= '1999-12-01 23:59:00.000'; select * from test where d= '1999-12-01 23:59:00.000';
> ID D > ID D
> -- --------------------- > -- -------------------
> 1 1999-12-01 23:59:00.0 > 1 1999-12-01 23:59:00
> rows: 1 > rows: 1
select * from test where d= timestamp '2006-01-01 12:00:00.000'; select * from test where d= timestamp '2006-01-01 12:00:00.000';
> ID D > ID D
> -- --------------------- > -- -------------------
> 1 2006-01-01 12:00:00.0 > 1 2006-01-01 12:00:00
> rows: 1 > rows: 1
drop table test; drop table test;
...@@ -2684,9 +2684,9 @@ select x/10 y from system_range(1, 100) group by x/10; ...@@ -2684,9 +2684,9 @@ select x/10 y from system_range(1, 100) group by x/10;
> rows: 11 > rows: 11
select timestamp '2001-02-03T10:30:33'; select timestamp '2001-02-03T10:30:33';
> TIMESTAMP '2001-02-03 10:30:33.0' > TIMESTAMP '2001-02-03 10:30:33'
> --------------------------------- > -------------------------------
> 2001-02-03 10:30:33.0 > 2001-02-03 10:30:33
> rows: 1 > rows: 1
CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255)); CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255));
...@@ -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');
...@@ -6911,8 +6911,8 @@ INSERT INTO TEST VALUES(NULL,NULL,NULL,NULL); ...@@ -6911,8 +6911,8 @@ INSERT INTO TEST VALUES(NULL,NULL,NULL,NULL);
SELECT * FROM TEST; SELECT * FROM TEST;
> ID XT XD XTS > ID XT XD XTS
> ---- -------- ---------- ----------------------------- > ---- -------- ---------- -----------------------------
> 0 00:00:00 0001-02-03 0002-03-04 00:00:00.0 > 0 00:00:00 0001-02-03 0002-03-04 00:00:00
> 1 01:02:03 0004-05-06 0007-08-09 00:01:02.0 > 1 01:02:03 0004-05-06 0007-08-09 00:01:02
> 2 23:59:59 1999-12-31 1999-12-31 23:59:59.123456789 > 2 23:59:59 1999-12-31 1999-12-31 23:59:59.123456789
> null null null null > null null null null
> rows: 4 > rows: 4
...@@ -6927,24 +6927,24 @@ SELECT XD+1, XD-1, XD-XD FROM TEST; ...@@ -6927,24 +6927,24 @@ SELECT XD+1, XD-1, XD-XD FROM TEST;
> rows: 4 > rows: 4
SELECT ID, CAST(XT AS DATE) T2D, CAST(XTS AS DATE) TS2D, SELECT ID, CAST(XT AS DATE) T2D, CAST(XTS AS DATE) TS2D,
CAST(XD AS TIME) D2T, CAST(XTS AS TIME) TS2T, CAST(XD AS TIME) D2T, CAST(XTS AS TIME(9)) TS2T,
CAST(XT AS TIMESTAMP) D2TS, CAST(XD AS TIMESTAMP) D2TS FROM TEST; CAST(XT AS TIMESTAMP) D2TS, CAST(XD AS TIMESTAMP) D2TS FROM TEST;
> ID T2D TS2D D2T TS2T D2TS D2TS > ID T2D TS2D D2T TS2T D2TS D2TS
> ---- ---------- ---------- -------- ------------------ --------------------- --------------------- > ---- ---------- ---------- -------- ------------------ ------------------- -------------------
> 0 1970-01-01 0002-03-04 00:00:00 00:00:00 1970-01-01 00:00:00.0 0001-02-03 00:00:00.0 > 0 1970-01-01 0002-03-04 00:00:00 00:00:00 1970-01-01 00:00:00 0001-02-03 00:00:00
> 1 1970-01-01 0007-08-09 00:00:00 00:01:02 1970-01-01 01:02:03.0 0004-05-06 00:00:00.0 > 1 1970-01-01 0007-08-09 00:00:00 00:01:02 1970-01-01 01:02:03 0004-05-06 00:00:00
> 2 1970-01-01 1999-12-31 00:00:00 23:59:59.123456789 1970-01-01 23:59:59.0 1999-12-31 00:00:00.0 > 2 1970-01-01 1999-12-31 00:00:00 23:59:59.123456789 1970-01-01 23:59:59 1999-12-31 00:00:00
> null null null null null null null > null null null null null null null
> rows: 4 > rows: 4
SCRIPT SIMPLE NOPASSWORDS NOSETTINGS; 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');
> 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');
> INSERT INTO PUBLIC.TEST(ID, XT, XD, XTS) VALUES(2, TIME '23:59:59', DATE '1999-12-31', TIMESTAMP '1999-12-31 23:59:59.123456789'); > INSERT INTO PUBLIC.TEST(ID, XT, XD, XTS) VALUES(2, TIME '23:59:59', DATE '1999-12-31', TIMESTAMP '1999-12-31 23:59:59.123456789');
> INSERT INTO PUBLIC.TEST(ID, XT, XD, XTS) VALUES(NULL, NULL, NULL, NULL); > INSERT INTO PUBLIC.TEST(ID, XT, XD, XTS) VALUES(NULL, NULL, NULL, NULL);
> rows: 7 > rows: 7
...@@ -6959,9 +6959,9 @@ INSERT INTO TEST VALUES(1, '2001-01-01 12:34:56.789123', '2001-01-01 12:34:56.78 ...@@ -6959,9 +6959,9 @@ INSERT INTO TEST VALUES(1, '2001-01-01 12:34:56.789123', '2001-01-01 12:34:56.78
> update count: 1 > update count: 1
select * from test; select * from test;
> ID T0 T1 T2 T5 > ID T0 T1 T2 T5
> -- --------------------- --------------------- ---------------------- ------------------------- > -- ------------------- --------------------- ---------------------- -------------------------
> 1 2001-01-01 12:34:57.0 2001-01-01 12:34:56.8 2001-01-01 12:34:56.79 2001-01-01 12:34:56.78912 > 1 2001-01-01 12:34:57 2001-01-01 12:34:56.8 2001-01-01 12:34:56.79 2001-01-01 12:34:56.78912
> rows: 1 > rows: 1
DROP TABLE IF EXISTS TEST; DROP TABLE IF EXISTS TEST;
......
...@@ -1235,7 +1235,7 @@ public class TestMVTableEngine extends TestBase { ...@@ -1235,7 +1235,7 @@ public class TestMVTableEngine extends TestBase {
assertEquals(3d, rs.getFloat(10)); assertEquals(3d, rs.getFloat(10));
assertEquals("10:00:00", rs.getString(11)); assertEquals("10:00:00", rs.getString(11));
assertEquals("2001-01-01", rs.getString(12)); assertEquals("2001-01-01", rs.getString(12));
assertEquals("2010-10-10 10:10:10.0", rs.getString(13)); assertEquals("2010-10-10 10:10:10", rs.getString(13));
assertEquals(1, rs.getBytes(14).length); assertEquals(1, rs.getBytes(14).length);
assertEquals("00000000-0000-0000-0000-000000000000", assertEquals("00000000-0000-0000-0000-000000000000",
rs.getString(15)); rs.getString(15));
...@@ -1254,7 +1254,7 @@ public class TestMVTableEngine extends TestBase { ...@@ -1254,7 +1254,7 @@ public class TestMVTableEngine extends TestBase {
assertEquals(32d, rs.getFloat(10)); assertEquals(32d, rs.getFloat(10));
assertEquals("10:00:00", rs.getString(11)); assertEquals("10:00:00", rs.getString(11));
assertEquals("2001-01-01", rs.getString(12)); assertEquals("2001-01-01", rs.getString(12));
assertEquals("2010-10-10 10:10:10.0", rs.getString(13)); assertEquals("2010-10-10 10:10:10", rs.getString(13));
assertEquals(1, rs.getBytes(14).length); assertEquals(1, rs.getBytes(14).length);
assertEquals("00000000-0000-0000-0000-000000000000", assertEquals("00000000-0000-0000-0000-000000000000",
rs.getString(15)); rs.getString(15));
...@@ -1274,7 +1274,7 @@ public class TestMVTableEngine extends TestBase { ...@@ -1274,7 +1274,7 @@ public class TestMVTableEngine extends TestBase {
assertEquals(0.0d, rs.getFloat(10)); assertEquals(0.0d, rs.getFloat(10));
assertEquals("10:00:00", rs.getString(11)); assertEquals("10:00:00", rs.getString(11));
assertEquals("2001-01-01", rs.getString(12)); assertEquals("2001-01-01", rs.getString(12));
assertEquals("2010-10-10 10:10:10.0", rs.getString(13)); assertEquals("2010-10-10 10:10:10", rs.getString(13));
assertEquals(100, rs.getBytes(14).length); assertEquals(100, rs.getBytes(14).length);
assertEquals("00000000-0000-0000-0000-000000000000", assertEquals("00000000-0000-0000-0000-000000000000",
rs.getString(15)); rs.getString(15));
...@@ -1293,7 +1293,7 @@ public class TestMVTableEngine extends TestBase { ...@@ -1293,7 +1293,7 @@ public class TestMVTableEngine extends TestBase {
assertEquals(1.0d, rs.getFloat(10)); assertEquals(1.0d, rs.getFloat(10));
assertEquals("10:00:00", rs.getString(11)); assertEquals("10:00:00", rs.getString(11));
assertEquals("2001-01-01", rs.getString(12)); assertEquals("2001-01-01", rs.getString(12));
assertEquals("2010-10-10 10:10:10.0", rs.getString(13)); assertEquals("2010-10-10 10:10:10", rs.getString(13));
assertEquals(100, rs.getBytes(14).length); assertEquals(100, rs.getBytes(14).length);
assertEquals("00000000-0000-0000-0000-000000000000", assertEquals("00000000-0000-0000-0000-000000000000",
rs.getString(15)); rs.getString(15));
......
...@@ -97,11 +97,11 @@ public class TestDate extends TestBase { ...@@ -97,11 +97,11 @@ public class TestDate extends TestBase {
// can't convert using java.util.Date // can't convert using java.util.Date
assertEquals( assertEquals(
Integer.MAX_VALUE + "-12-31 00:00:00.0", Integer.MAX_VALUE + "-12-31 00:00:00",
ValueDate.parse(Integer.MAX_VALUE + "-12-31"). ValueDate.parse(Integer.MAX_VALUE + "-12-31").
convertTo(Value.TIMESTAMP).getString()); convertTo(Value.TIMESTAMP).getString());
assertEquals( assertEquals(
Integer.MIN_VALUE + "-12-31 00:00:00.0", Integer.MIN_VALUE + "-12-31 00:00:00",
ValueDate.parse(Integer.MIN_VALUE + "-12-31"). ValueDate.parse(Integer.MIN_VALUE + "-12-31").
convertTo(Value.TIMESTAMP).getString()); convertTo(Value.TIMESTAMP).getString());
assertEquals( assertEquals(
...@@ -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);
...@@ -220,7 +221,7 @@ public class TestDate extends TestBase { ...@@ -220,7 +221,7 @@ public class TestDate extends TestBase {
@SuppressWarnings("unlikely-arg-type") @SuppressWarnings("unlikely-arg-type")
private void testValueTimestamp() { private void testValueTimestamp() {
assertEquals( assertEquals(
"2001-02-03 04:05:06.0", ValueTimestamp.get( "2001-02-03 04:05:06", ValueTimestamp.get(
Timestamp.valueOf( Timestamp.valueOf(
"2001-02-03 04:05:06")).getString()); "2001-02-03 04:05:06")).getString());
assertEquals( assertEquals(
...@@ -228,9 +229,9 @@ public class TestDate extends TestBase { ...@@ -228,9 +229,9 @@ public class TestDate extends TestBase {
Timestamp.valueOf( Timestamp.valueOf(
"2001-02-03 04:05:06.001002003")).getString()); "2001-02-03 04:05:06.001002003")).getString());
assertEquals( assertEquals(
"0-00-00 00:00:00.0", ValueTimestamp.fromDateValueAndNanos(0, 0).getString()); "0-00-00 00:00:00", ValueTimestamp.fromDateValueAndNanos(0, 0).getString());
assertEquals( assertEquals(
"9999-12-31 23:59:59.0", "9999-12-31 23:59:59",
ValueTimestamp.parse( ValueTimestamp.parse(
"9999-12-31 23:59:59").getString()); "9999-12-31 23:59:59").getString());
...@@ -257,9 +258,10 @@ public class TestDate extends TestBase { ...@@ -257,9 +258,10 @@ 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(10, t1.getScale()); assertEquals(ValueTimestamp.MAXIMUM_PRECISION, t1.getPrecision());
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);
...@@ -299,7 +301,7 @@ public class TestDate extends TestBase { ...@@ -299,7 +301,7 @@ public class TestDate extends TestBase {
t1.convertScale(true, 2).getString()); t1.convertScale(true, 2).getString());
assertEquals("2001-01-01 01:01:01.1", assertEquals("2001-01-01 01:01:01.1",
t1.convertScale(true, 1).getString()); t1.convertScale(true, 1).getString());
assertEquals("2001-01-01 01:01:01.0", assertEquals("2001-01-01 01:01:01",
t1.convertScale(true, 0).getString()); t1.convertScale(true, 0).getString());
t1 = ValueTimestamp.parse("-2001-01-01 01:01:01.123456789"); t1 = ValueTimestamp.parse("-2001-01-01 01:01:01.123456789");
assertEquals("-2001-01-01 01:01:01.123457", assertEquals("-2001-01-01 01:01:01.123457",
...@@ -308,24 +310,24 @@ public class TestDate extends TestBase { ...@@ -308,24 +310,24 @@ public class TestDate extends TestBase {
assertFalse(ValueTimestamp.parse("2001-01-01"). assertFalse(ValueTimestamp.parse("2001-01-01").
equals(ValueDate.parse("2001-01-01"))); equals(ValueDate.parse("2001-01-01")));
assertEquals("2001-01-01 01:01:01.0", assertEquals("2001-01-01 01:01:01",
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("1010-10-10 00:00:00.0", assertEquals("1010-10-10 00:00:00",
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("-2001-01-01 01:01:01.0", assertEquals("-2001-01-01 01:01:01",
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("-1010-10-10 00:00:00.0", assertEquals("-1010-10-10 00:00:00",
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) { if (SysProperties.UNLIMITED_TIME_RANGE) {
assertEquals("2001-01-02 01:01:01.0", assertEquals("2001-01-02 01:01:01",
ValueTimestamp.parse("2001-01-01").add( ValueTimestamp.parse("2001-01-01").add(
ValueTime.parse("25:01:01")).getString()); ValueTime.parse("25:01:01")).getString());
assertEquals("1010-10-10 10:00:00.0", assertEquals("1010-10-10 10:00:00",
ValueTimestamp.parse("1010-10-11 10:10:10").subtract( ValueTimestamp.parse("1010-10-11 10:10:10").subtract(
ValueTime.parse("24:10:10")).getString()); ValueTime.parse("24:10:10")).getString());
} }
......
...@@ -46,6 +46,7 @@ public class TestDateTimeUtils extends TestBase { ...@@ -46,6 +46,7 @@ public class TestDateTimeUtils extends TestBase {
testWeekOfYear(); testWeekOfYear();
testDateValueFromDenormalizedDate(); testDateValueFromDenormalizedDate();
testUTC2Value(false); testUTC2Value(false);
testConvertScale();
} }
private void testParseTimeNanosDB2Format() { private void testParseTimeNanosDB2Format() {
...@@ -160,4 +161,37 @@ public class TestDateTimeUtils extends TestBase { ...@@ -160,4 +161,37 @@ public class TestDateTimeUtils extends TestBase {
} }
} }
private void testConvertScale() {
assertEquals(555_555_555_555L, DateTimeUtils.convertScale(555_555_555_555L, 9));
assertEquals(555_555_555_550L, DateTimeUtils.convertScale(555_555_555_554L, 8));
assertEquals(555_555_555_500L, DateTimeUtils.convertScale(555_555_555_549L, 7));
assertEquals(555_555_555_000L, DateTimeUtils.convertScale(555_555_555_499L, 6));
assertEquals(555_555_550_000L, DateTimeUtils.convertScale(555_555_554_999L, 5));
assertEquals(555_555_500_000L, DateTimeUtils.convertScale(555_555_549_999L, 4));
assertEquals(555_555_000_000L, DateTimeUtils.convertScale(555_555_499_999L, 3));
assertEquals(555_550_000_000L, DateTimeUtils.convertScale(555_554_999_999L, 2));
assertEquals(555_500_000_000L, DateTimeUtils.convertScale(555_549_999_999L, 1));
assertEquals(555_000_000_000L, DateTimeUtils.convertScale(555_499_999_999L, 0));
assertEquals(555_555_555_555L, DateTimeUtils.convertScale(555_555_555_555L, 9));
assertEquals(555_555_555_560L, DateTimeUtils.convertScale(555_555_555_555L, 8));
assertEquals(555_555_555_600L, DateTimeUtils.convertScale(555_555_555_550L, 7));
assertEquals(555_555_556_000L, DateTimeUtils.convertScale(555_555_555_500L, 6));
assertEquals(555_555_560_000L, DateTimeUtils.convertScale(555_555_555_000L, 5));
assertEquals(555_555_600_000L, DateTimeUtils.convertScale(555_555_550_000L, 4));
assertEquals(555_556_000_000L, DateTimeUtils.convertScale(555_555_500_000L, 3));
assertEquals(555_560_000_000L, DateTimeUtils.convertScale(555_555_000_000L, 2));
assertEquals(555_600_000_000L, DateTimeUtils.convertScale(555_550_000_000L, 1));
assertEquals(556_000_000_000L, DateTimeUtils.convertScale(555_500_000_000L, 0));
assertEquals(100_999_999_999L, DateTimeUtils.convertScale(100_999_999_999L, 9));
assertEquals(101_000_000_000L, DateTimeUtils.convertScale(100_999_999_999L, 8));
assertEquals(101_000_000_000L, DateTimeUtils.convertScale(100_999_999_999L, 7));
assertEquals(101_000_000_000L, DateTimeUtils.convertScale(100_999_999_999L, 6));
assertEquals(101_000_000_000L, DateTimeUtils.convertScale(100_999_999_999L, 5));
assertEquals(101_000_000_000L, DateTimeUtils.convertScale(100_999_999_999L, 4));
assertEquals(101_000_000_000L, DateTimeUtils.convertScale(100_999_999_999L, 3));
assertEquals(101_000_000_000L, DateTimeUtils.convertScale(100_999_999_999L, 2));
assertEquals(101_000_000_000L, DateTimeUtils.convertScale(100_999_999_999L, 1));
assertEquals(101_000_000_000L, DateTimeUtils.convertScale(100_999_999_999L, 0));
}
} }
...@@ -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')");
...@@ -62,7 +62,7 @@ public class TestTimeStampWithTimeZone extends TestBase { ...@@ -62,7 +62,7 @@ public class TestTimeStampWithTimeZone extends TestBase {
stat.execute("insert into test(t1) values('2015-12-31 19:00:00.00-10:00')"); stat.execute("insert into test(t1) values('2015-12-31 19:00:00.00-10:00')");
ResultSet rs = stat.executeQuery("select t1 from test"); ResultSet rs = stat.executeQuery("select t1 from test");
rs.next(); rs.next();
assertEquals("1970-01-01 12:00:00.0+00:15", rs.getString(1)); assertEquals("1970-01-01 12:00:00+00:15", rs.getString(1));
TimestampWithTimeZone ts = (TimestampWithTimeZone) rs.getObject(1); TimestampWithTimeZone ts = (TimestampWithTimeZone) rs.getObject(1);
assertEquals(1970, ts.getYear()); assertEquals(1970, ts.getYear());
assertEquals(1, ts.getMonth()); assertEquals(1, ts.getMonth());
...@@ -188,7 +188,7 @@ public class TestTimeStampWithTimeZone extends TestBase { ...@@ -188,7 +188,7 @@ public class TestTimeStampWithTimeZone extends TestBase {
stat.execute("insert into test_order(t1) values('1970-01-01 12:00:01.00+01:15')"); stat.execute("insert into test_order(t1) values('1970-01-01 12:00:01.00+01:15')");
ResultSet rs = stat.executeQuery("select t1 from test_order order by t1"); ResultSet rs = stat.executeQuery("select t1 from test_order order by t1");
rs.next(); rs.next();
assertEquals("1970-01-01 12:00:01.0+01:15", rs.getString(1)); assertEquals("1970-01-01 12:00:01+01:15", rs.getString(1));
conn.close(); conn.close();
} }
......
...@@ -764,7 +764,7 @@ public class TestTools extends TestBase { ...@@ -764,7 +764,7 @@ public class TestTools extends TestBase {
assertEquals(new byte[] { (byte) 10, (byte) 20 }, rs.getBytes("f")); assertEquals(new byte[] { (byte) 10, (byte) 20 }, rs.getBytes("f"));
assertEquals("2007-12-31", rs.getString("g")); assertEquals("2007-12-31", rs.getString("g"));
assertEquals("23:59:59", rs.getString("h")); assertEquals("23:59:59", rs.getString("h"));
assertEquals("2007-12-31 23:59:59.0", rs.getString("i")); assertEquals("2007-12-31 23:59:59", rs.getString("i"));
assertFalse(rs.next()); assertFalse(rs.next());
conn.close(); conn.close();
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论