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
"
"Data Types","TIME Type","
TIME [ WITHOUT TIME ZONE ]
TIME [ ( precisionInt ) ] [ WITHOUT TIME ZONE ]
","
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"".
""java.time.LocalTime"" is also supported on Java 8 and later versions.
......@@ -2472,10 +2473,11 @@ DATE
"
"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].
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).
""java.time.LocalDateTime"" is also supported on Java 8 and later versions.
......@@ -2484,10 +2486,11 @@ TIMESTAMP
"
"Data Types","TIMESTAMP WITH TIME ZONE Type","
TIMESTAMP WITH TIME ZONE
TIMESTAMP [ ( precisionInt ) ] WITH TIME ZONE
","
The timestamp with time zone data type.
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"".
""java.time.OffsetDateTime"" and ""java.time.Instant"" are also supported on Java 8 and later versions.
......
......@@ -4343,6 +4343,7 @@ public class Parser {
private Column parseColumnWithType(String columnName) {
String original = currentToken;
boolean regular = false;
int originalScale = -1;
if (readIf("LONG")) {
if (readIf("RAW")) {
original += " RAW";
......@@ -4356,12 +4357,30 @@ public class Parser {
original += " VARYING";
}
} 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")) {
read("TIME");
read("ZONE");
original += " WITHOUT TIME ZONE";
}
} 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")) {
read("TIME");
read("ZONE");
......@@ -4415,7 +4434,34 @@ public class Parser {
: displaySize;
scale = scale == -1 ? dataType.defaultScale : scale;
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")) {
long p = readLong();
if (readIf("K")) {
......@@ -4436,14 +4482,7 @@ public class Parser {
scale = readInt();
original += ", " + scale;
} else {
// special case: TIMESTAMP(5) actually means
// TIMESTAMP(23, 5)
if (dataType.type == Value.TIMESTAMP) {
scale = MathUtils.convertLongToInt(p);
p = precision;
} else {
scale = 0;
}
scale = 0;
}
}
precision = p;
......
......@@ -2590,7 +2590,7 @@ public class Function extends Expression implements FunctionCall {
t = Value.DATE;
p = ValueDate.PRECISION;
s = 0;
d = ValueDate.DISPLAY_SIZE;
d = ValueDate.PRECISION;
}
break;
case ABS:
......
......@@ -295,10 +295,10 @@ public class TableLink extends Table {
precision = Math.max(ValueDate.PRECISION, precision);
break;
case Types.TIMESTAMP:
precision = Math.max(ValueTimestamp.PRECISION, precision);
precision = Math.max(ValueTimestamp.MAXIMUM_PRECISION, precision);
break;
case Types.TIME:
precision = Math.max(ValueTime.PRECISION, precision);
precision = Math.max(ValueTime.MAXIMUM_PRECISION, precision);
break;
}
return precision;
......
......@@ -69,6 +69,12 @@ public class DateTimeUtils {
private static final int[] DAYS_OFFSET = { 0, 31, 61, 92, 122, 153, 184,
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
* in an inner class, which would not be garbage collected in a web
......@@ -1340,10 +1346,8 @@ public class DateTimeUtils {
*
* @param buff the target string builder
* @param nanos the time in nanoseconds
* @param alwaysAddMillis whether to always add at least ".0"
*/
public static void appendTime(StringBuilder buff, long nanos,
boolean alwaysAddMillis) {
public static void appendTime(StringBuilder buff, long nanos) {
if (nanos < 0) {
buff.append('-');
nanos = -nanos;
......@@ -1367,7 +1371,7 @@ public class DateTimeUtils {
StringUtils.appendZeroPadded(buff, 2, m);
buff.append(':');
StringUtils.appendZeroPadded(buff, 2, s);
if (alwaysAddMillis || ms > 0 || nanos > 0) {
if (ms > 0 || nanos > 0) {
buff.append('.');
int start = buff.length();
StringUtils.appendZeroPadded(buff, 3, ms);
......@@ -1415,10 +1419,10 @@ public class DateTimeUtils {
* @return formatted string
*/
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);
buff.append(' ');
appendTime(buff, timeNanos, true);
appendTime(buff, timeNanos);
appendTimeZone(buff, timeZoneOffsetMins);
return buff.toString();
}
......@@ -1448,4 +1452,23 @@ public class DateTimeUtils {
return b.toString();
}
/**
* Converts scale of nanoseconds.
*
* @param nanosOfDay nanoseconds of day
* @param scale fractional seconds precision
* @return scaled value
*/
public static long convertScale(long nanosOfDay, int scale) {
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 {
24
);
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"},
// 24 for ValueTime, 32 for java.sql.Time
56
);
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"},
// 24 for ValueDate, 32 for java.sql.Data
56
);
add(Value.TIMESTAMP, Types.TIMESTAMP,
createDate(ValueTimestamp.PRECISION, "TIMESTAMP",
ValueTimestamp.DEFAULT_SCALE, ValueTimestamp.DISPLAY_SIZE),
createDate(ValueTimestamp.MAXIMUM_PRECISION, ValueTimestamp.DEFAULT_PRECISION,
"TIMESTAMP", true, ValueTimestamp.DEFAULT_SCALE, ValueTimestamp.MAXIMUM_SCALE),
new String[]{"TIMESTAMP", "TIMESTAMP WITHOUT TIME ZONE",
"DATETIME", "DATETIME2", "SMALLDATETIME"},
// 24 for ValueTimestamp, 32 for java.sql.Timestamp
......@@ -306,8 +308,9 @@ public class DataType {
// compile (on Java 1.7). Can be replaced with
// Types.TIMESTAMP_WITH_TIMEZONE once Java 1.8 is required.
add(Value.TIMESTAMP_TZ, 2014,
createDate(ValueTimestampTimeZone.PRECISION, "TIMESTAMP_TZ",
ValueTimestampTimeZone.DEFAULT_SCALE, ValueTimestampTimeZone.DISPLAY_SIZE),
createDate(ValueTimestampTimeZone.MAXIMUM_PRECISION, ValueTimestampTimeZone.DEFAULT_PRECISION,
"TIMESTAMP_TZ", true, ValueTimestampTimeZone.DEFAULT_SCALE,
ValueTimestampTimeZone.MAXIMUM_SCALE),
new String[]{"TIMESTAMP WITH TIME ZONE"},
// 26 for ValueTimestampUtc, 32 for java.sql.Timestamp
58
......@@ -461,17 +464,17 @@ public class DataType {
return dataType;
}
private static DataType createDate(int precision, String prefix, int scale,
int displaySize) {
private static DataType createDate(int maxPrecision, int precision, String prefix, boolean supportsScale, int scale,
int maxScale) {
DataType dataType = new DataType();
dataType.prefix = prefix + " '";
dataType.suffix = "'";
dataType.maxPrecision = precision;
dataType.supportsScale = scale != 0;
dataType.maxScale = scale;
dataType.maxPrecision = maxPrecision;
dataType.supportsScale = supportsScale;
dataType.maxScale = maxScale;
dataType.defaultPrecision = precision;
dataType.defaultScale = scale;
dataType.defaultDisplaySize = displaySize;
dataType.defaultDisplaySize = precision;
return dataType;
}
......
......@@ -19,15 +19,10 @@ import org.h2.util.DateTimeUtils;
public class ValueDate extends Value {
/**
* The precision in digits.
*/
public static final int PRECISION = 8;
/**
* The display size of the textual representation of a date.
* The default precision and display size of the textual representation of a date.
* Example: 2000-01-02
*/
public static final int DISPLAY_SIZE = 10;
public static final int PRECISION = 10;
private final long dateValue;
......@@ -97,7 +92,7 @@ public class ValueDate extends Value {
@Override
public String getString() {
StringBuilder buff = new StringBuilder(DISPLAY_SIZE);
StringBuilder buff = new StringBuilder(PRECISION);
DateTimeUtils.appendDate(buff, dateValue);
return buff.toString();
}
......@@ -114,7 +109,7 @@ public class ValueDate extends Value {
@Override
public int getDisplaySize() {
return DISPLAY_SIZE;
return PRECISION;
}
@Override
......
......@@ -19,15 +19,36 @@ import org.h2.util.DateTimeUtils;
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.
* Example: 10:00:00
* The maximum precision and display size of the textual representation of a time.
* 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
......@@ -51,7 +72,7 @@ public class ValueTime extends Value {
if (!SysProperties.UNLIMITED_TIME_RANGE) {
if (nanos < 0L || nanos >= 86400000000000L) {
StringBuilder builder = new StringBuilder();
DateTimeUtils.appendTime(builder, nanos, false);
DateTimeUtils.appendTime(builder, nanos);
throw DbException.get(ErrorCode.INVALID_DATETIME_CONSTANT_2,
"TIME", builder.toString());
}
......@@ -114,8 +135,8 @@ public class ValueTime extends Value {
@Override
public String getString() {
StringBuilder buff = new StringBuilder(DISPLAY_SIZE);
DateTimeUtils.appendTime(buff, nanos, false);
StringBuilder buff = new StringBuilder(MAXIMUM_PRECISION);
DateTimeUtils.appendTime(buff, nanos);
return buff.toString();
}
......@@ -126,12 +147,37 @@ public class ValueTime extends Value {
@Override
public long getPrecision() {
return PRECISION;
return MAXIMUM_PRECISION;
}
@Override
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
......
......@@ -5,7 +5,6 @@
*/
package org.h2.value;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
......@@ -20,20 +19,36 @@ import org.h2.util.DateTimeUtils;
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.
* Example: 2001-01-01 23:59:59.000
* The maximum precision and display size of the textual representation of a timestamp.
* 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.
*/
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
......@@ -165,10 +180,10 @@ public class ValueTimestamp extends Value {
@Override
public String getString() {
StringBuilder buff = new StringBuilder(DISPLAY_SIZE);
StringBuilder buff = new StringBuilder(MAXIMUM_PRECISION);
DateTimeUtils.appendDate(buff, dateValue);
buff.append(' ');
DateTimeUtils.appendTime(buff, timeNanos, true);
DateTimeUtils.appendTime(buff, timeNanos);
return buff.toString();
}
......@@ -179,37 +194,44 @@ public class ValueTimestamp extends Value {
@Override
public long getPrecision() {
return PRECISION;
return MAXIMUM_PRECISION;
}
@Override
public int getScale() {
return DEFAULT_SCALE;
return MAXIMUM_SCALE;
}
@Override
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
public Value convertScale(boolean onlyToSmallerScale, int targetScale) {
if (targetScale >= DEFAULT_SCALE) {
if (targetScale >= MAXIMUM_SCALE) {
return this;
}
if (targetScale < 0) {
throw DbException.getInvalidValueException("scale", targetScale);
}
long n = timeNanos;
BigDecimal bd = BigDecimal.valueOf(n);
bd = bd.movePointLeft(9);
bd = ValueDecimal.setScale(bd, targetScale);
bd = bd.movePointRight(9);
long n2 = bd.longValue();
long n2 = DateTimeUtils.convertScale(n, targetScale);
if (n2 == n) {
return this;
}
return fromDateValueAndNanos(dateValue, n2);
long dv = dateValue;
if (n2 >= DateTimeUtils.NANOS_PER_DAY) {
n2 -= DateTimeUtils.NANOS_PER_DAY;
dv = DateTimeUtils.dateValueFromAbsoluteDay(DateTimeUtils.absoluteDayFromDateValue(dateValue) + 1);
}
return fromDateValueAndNanos(dv, n2);
}
@Override
......
......@@ -5,7 +5,6 @@
*/
package org.h2.value;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
......@@ -23,20 +22,36 @@ import org.h2.util.DateTimeUtils;
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:
* 2001-01-01 23:59:59.000 +10:00
* The maximum precision and display size of the textual representation of a timestamp.
* 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.
*/
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
......@@ -168,37 +183,44 @@ public class ValueTimestampTimeZone extends Value {
@Override
public long getPrecision() {
return PRECISION;
return MAXIMUM_PRECISION;
}
@Override
public int getScale() {
return DEFAULT_SCALE;
return MAXIMUM_SCALE;
}
@Override
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
public Value convertScale(boolean onlyToSmallerScale, int targetScale) {
if (targetScale >= DEFAULT_SCALE) {
if (targetScale >= MAXIMUM_SCALE) {
return this;
}
if (targetScale < 0) {
throw DbException.getInvalidValueException("scale", targetScale);
}
long n = timeNanos;
BigDecimal bd = BigDecimal.valueOf(n);
bd = bd.movePointLeft(9);
bd = ValueDecimal.setScale(bd, targetScale);
bd = bd.movePointRight(9);
long n2 = bd.longValue();
long n2 = DateTimeUtils.convertScale(n, targetScale);
if (n2 == n) {
return this;
}
return fromDateValueAndNanos(dateValue, n2, timeZoneOffsetMins);
long dv = dateValue;
if (n2 >= DateTimeUtils.NANOS_PER_DAY) {
n2 -= DateTimeUtils.NANOS_PER_DAY;
dv = DateTimeUtils.dateValueFromAbsoluteDay(DateTimeUtils.absoluteDayFromDateValue(dateValue) + 1);
}
return fromDateValueAndNanos(dv, n2, timeZoneOffsetMins);
}
@Override
......
......@@ -84,26 +84,26 @@ public class TestDateStorage extends TestBase {
prep.execute();
rs = stat.executeQuery("select * from ts order by x");
rs.next();
assertEquals("2010-03-14 02:15:00.0",
assertEquals("2010-03-14 02:15:00",
rs.getString(1));
assertEquals("2010-03-13 18:15:00.0",
rs.getTimestamp(1, utcCalendar).toString());
assertEquals("2010-03-14 03:15:00.0",
rs.getTimestamp(1).toString());
assertEquals("2010-03-14 02:15:00.0",
assertEquals("2010-03-14 02:15:00",
rs.getString("x"));
assertEquals("2010-03-13 18:15:00.0",
rs.getTimestamp("x", utcCalendar).toString());
assertEquals("2010-03-14 03:15:00.0",
rs.getTimestamp("x").toString());
rs.next();
assertEquals("2010-03-14 03:15:00.0",
assertEquals("2010-03-14 03:15:00",
rs.getString(1));
assertEquals("2010-03-13 19:15:00.0",
rs.getTimestamp(1, utcCalendar).toString());
assertEquals("2010-03-14 03:15:00.0",
rs.getTimestamp(1).toString());
assertEquals("2010-03-14 03:15:00.0",
assertEquals("2010-03-14 03:15:00",
rs.getString("x"));
assertEquals("2010-03-13 19:15:00.0",
rs.getTimestamp("x", utcCalendar).toString());
......
......@@ -328,7 +328,7 @@ public class TestFunctions extends TestBase implements AggregateFunction {
rs = stat.executeQuery(
"call TO_CHAR_2(TIMESTAMP '2001-02-03 04:05:06', 'format')");
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");
conn.close();
}
......
......@@ -85,7 +85,7 @@ public class SupportedTypes {
s.myString = Long.toHexString(rand.nextLong());
s.myUtilDate = new java.util.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());
return s;
}
......
......@@ -723,9 +723,9 @@ public class TestMetaData extends TestBase {
"" + DatabaseMetaData.columnNullable, "", null,
"" + numericType, "0", "12", "3", "YES" },
{ CATALOG, Constants.SCHEMA_MAIN, "TEST", "DATE_V",
"" + Types.TIMESTAMP, "TIMESTAMP", "23", "23", "10",
"" + Types.TIMESTAMP, "TIMESTAMP", "26", "26", "6",
"10", "" + DatabaseMetaData.columnNullable, "", null,
"" + Types.TIMESTAMP, "0", "23", "4", "YES" },
"" + Types.TIMESTAMP, "0", "26", "4", "YES" },
{ CATALOG, Constants.SCHEMA_MAIN, "TEST", "BLOB_V",
"" + Types.BLOB, "BLOB", "" + Integer.MAX_VALUE,
"" + Integer.MAX_VALUE, "0", "10",
......
......@@ -1262,13 +1262,13 @@ public class TestResultSet extends TestBase {
assertEquals("99999-12-23", rs.getString(1));
rs = stat.executeQuery("call timestamp '99999-12-23 01:02:03.000'");
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.next();
assertEquals("-99999-12-23", rs.getString(1));
rs = stat.executeQuery("call timestamp '-99999-12-23 01:02:03.000'");
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("INSERT INTO TEST VALUES(1,DATE '2011-11-11')");
......@@ -1280,11 +1280,11 @@ public class TestResultSet extends TestBase {
"TIMESTAMP '9999-12-31 23:59:59' VALUE FROM TEST ORDER BY ID");
assertResultSetMeta(rs, 2, new String[] { "ID", "VALUE" },
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");
assertResultSetMeta(rs, 2, new String[] { "ID", "VALUE" },
new int[] { Types.INTEGER, Types.TIMESTAMP },
new int[] { 10, 23 }, new int[] { 0, 10 });
new int[] { 10, 26 }, new int[] { 0, 6 });
rs.next();
java.sql.Date date;
java.sql.Time time;
......@@ -1431,7 +1431,7 @@ public class TestResultSet extends TestBase {
ResultSet rs;
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(
"INSERT INTO TEST VALUES(?, ?, ?, ?)");
Calendar regular = DateTimeUtils.createGregorianCalendar();
......@@ -1494,7 +1494,7 @@ public class TestResultSet extends TestBase {
new String[] { "ID", "D", "T", "TS" },
new int[] { Types.INTEGER, Types.DATE,
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();
assertEquals(0, rs.getInt(1));
......
......@@ -296,7 +296,7 @@ public class TestUpdatableResultSet extends TestBase {
ResultSet.CONCUR_UPDATABLE);
stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255), "
+ "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)");
ResultSet rs = stat.executeQuery("SELECT * FROM TEST");
ResultSetMetaData meta = rs.getMetaData();
......
......@@ -23,6 +23,22 @@ SELECT COLUMN_NAME, DATA_TYPE, TYPE_NAME, COLUMN_TYPE FROM INFORMATION_SCHEMA.CO
> T2 92 TIME TIME WITHOUT TIME ZONE
> 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;
> ok
......@@ -41,3 +57,32 @@ SELECT TIME FROM TEST;
DROP TABLE TEST;
> 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');
SELECT "Query".* FROM (select * from tab_with_timezone where x > '2016-01-01') AS "Query";
> X
> ------------------------
> 2017-01-01 00:00:00.0+00
> ----------------------
> 2017-01-01 00:00:00+00
DELETE FROM tab_with_timezone;
> update count: 1
......@@ -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;
> X
> ------------------------
> 2018-03-25 01:59:00.0+01
> 2018-03-25 03:00:00.0+02
> ----------------------
> 2018-03-25 01:59:00+01
> 2018-03-25 03:00:00+02
> rows (ordered): 2
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 C,
TIMESTAMP WITH TIME ZONE '2000-01-10T00:00:00.000000000+09:00[Asia/Tokyo]' AS 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
> A B C D
> ---------------------- ---------------------- ---------------------- ----------------------
> 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
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
> update count: 1
SELECT T1, T2, T1 = T2 FROM TEST;
> T1 T2 T1 = T2
> --------------------- --------------------- -------
> 2010-01-01 10:00:00.0 2010-01-01 10:00:00.0 TRUE
> T1 T2 T1 = T2
> ------------------- ------------------- -------
> 2010-01-01 10:00:00 2010-01-01 10:00:00 TRUE
> 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;
> COLUMN_NAME DATA_TYPE TYPE_NAME COLUMN_TYPE
> ----------- --------- --------- ---------------------------
> T1 93 TIMESTAMP TIMESTAMP
> T2 93 TIMESTAMP TIMESTAMP WITHOUT TIME ZONE
> rows (ordered): 2
> COLUMN_NAME DATA_TYPE TYPE_NAME COLUMN_TYPE NUMERIC_SCALE
> ----------- --------- --------- ------------------------------ -------------
> T1 93 TIMESTAMP TIMESTAMP 6
> T2 93 TIMESTAMP TIMESTAMP WITHOUT TIME ZONE 6
> 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;
> ok
-- Check that TIMESTAMP is allowed as a column name
CREATE TABLE TEST(TIMESTAMP TIMESTAMP);
CREATE TABLE TEST(TIMESTAMP TIMESTAMP(0));
> ok
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;
> 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
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;
> ok
......@@ -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;
> MEDIAN(V)
> ---------------------
> 2000-01-20 20:00:00.0
> -------------------
> 2000-01-20 20:00:00
insert into test values (null);
> update count: 1
select median(v) from test;
> MEDIAN(V)
> ---------------------
> 2000-01-20 20:00:00.0
> -------------------
> 2000-01-20 20:00:00
select median(distinct v) from test;
> 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');
> update count: 1
select median(v) from test;
> MEDIAN(V)
> ---------------------
> 2000-01-15 15:00:00.0
> -------------------
> 2000-01-15 15:00:00
delete from test;
> update count: 5
......@@ -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;
> MEDIAN(V)
> ---------------------
> 2000-01-21 08:00:00.0
> -------------------
> 2000-01-21 08:00:00
drop table test;
> ok
......@@ -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;
> MEDIAN(V)
> ------------------------
> 2000-01-20 20:00:00.0+04
> ----------------------
> 2000-01-20 20:00:00+04
insert into test values (null);
> update count: 1
select median(v) from test;
> MEDIAN(V)
> ------------------------
> 2000-01-20 20:00:00.0+04
> ----------------------
> 2000-01-20 20:00:00+04
select median(distinct v) from test;
> 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');
> update count: 1
select median(v) from test;
> MEDIAN(V)
> ------------------------
> 2000-01-15 15:00:00.0+03
> ----------------------
> 2000-01-15 15:00:00+03
delete from test;
> 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'
select median(v) from test;
> MEDIAN(V)
> ---------------------------
> 2000-01-21 08:00:30.0+00:37
> -------------------------
> 2000-01-21 08:00:30+00:37
drop table test;
> ok
......
......@@ -6,22 +6,22 @@
-- 01-Aug-03 + 3 months = 01-Nov-03
SELECT ADD_MONTHS('2003-08-01', 3) AS R;
> R
> ---------------------
> 2003-11-01 00:00:00.0
> -------------------
> 2003-11-01 00:00:00
> rows: 1
-- 31-Jan-03 + 1 month = 28-Feb-2003
SELECT ADD_MONTHS('2003-01-31', 1) AS R;
> R
> ---------------------
> 2003-02-28 00:00:00.0
> -------------------
> 2003-02-28 00:00:00
> rows: 1
-- 21-Aug-2003 - 3 months = 21-May-2003
SELECT ADD_MONTHS('2003-08-21', -3) AS R;
> R
> ---------------------
> 2003-05-21 00:00:00.0
> -------------------
> 2003-05-21 00:00:00
> rows: 1
-- 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(
> 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;
> C1 C2 C3 C4 C5
> ---- ---- ---- ---- --
> TRUE TRUE TRUE TRUE .
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
> ---- ---- ---- ----
> TRUE TRUE TRUE TRUE
> rows: 1
......@@ -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;
> X
> ---------------------
> 2010-01-01 01:00:00.0
> -------------------
> 2010-01-01 01:00:00
> rows: 1
select ts + t + t - t x from test;
> X
> ---------------------
> 2010-01-01 01:00:00.0
> -------------------
> 2010-01-01 01:00:00
> rows: 1
select ts + t * 0.5 x from test;
> X
> ---------------------
> 2010-01-01 00:30:00.0
> -------------------
> 2010-01-01 00:30:00
> rows: 1
select ts + 0.5 x from test;
> X
> ---------------------
> 2010-01-01 12:00:00.0
> -------------------
> 2010-01-01 12:00:00
> rows: 1
select ts - 1.5 x from test;
> X
> ---------------------
> 2009-12-30 12:00:00.0
> -------------------
> 2009-12-30 12:00:00
> rows: 1
select ts + 0.5 * t + t - t x from test;
> X
> ---------------------
> 2010-01-01 00:30:00.0
> -------------------
> 2010-01-01 00:30:00
> rows: 1
select ts + t / 0.5 x from test;
> X
> ---------------------
> 2010-01-01 02:00:00.0
> -------------------
> 2010-01-01 02:00:00
> rows: 1
select d + t, t + d - t x from test;
> T + D X
> --------------------- ---------------------
> 2001-01-01 01:00:00.0 2001-01-01 00:00:00.0
> T + D X
> ------------------- -------------------
> 2001-01-01 01:00:00 2001-01-01 00:00:00
> rows: 1
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)
> --------------------------------------- --------------------- ---------------------------------------- ----------------------
> 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
select 1 + d + t + 1 from test;
> DATEADD('DAY', 1, (T + DATEADD('DAY', 1, D)))
> ---------------------------------------------
> 2001-01-03 01:00:00.0
> 2001-01-03 01:00:00
> rows: 1
select ts - t - 2 from test;
> DATEADD('DAY', -2, (TS - T))
> ----------------------------
> 2009-12-29 23:00:00.0
> 2009-12-29 23:00:00
> rows: 1
drop table test;
......@@ -118,9 +118,9 @@ SELECT DATEADD('NANOSECOND', 1, TIME '10:00:01'), DATEADD('NS', 1, TIMESTAMP '20
> rows: 1
SELECT DATEADD('HOUR', 1, DATE '2010-01-20');
> TIMESTAMP '2010-01-20 01:00:00.0'
> ---------------------------------
> 2010-01-20 01:00:00.0
> TIMESTAMP '2010-01-20 01:00:00'
> -------------------------------
> 2010-01-20 01:00:00
> rows: 1
SELECT DATEADD('MINUTE', 30, TIME '12:30:55');
......@@ -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;
> T
> ---------------------------
> 2010-01-01 10:00:00.0+08:30
> -------------------------
> 2010-01-01 10:00:00+08:30
> rows: 1
SELECT TIMESTAMPADD('TIMEZONE_MINUTE', -45, TIMESTAMP WITH TIME ZONE '2010-01-01 10:00:00+07:30') AS T;
> T
> ---------------------------
> 2010-01-01 10:00:00.0+06:45
> -------------------------
> 2010-01-01 10:00:00+06:45
> rows: 1
SELECT DATEADD(HOUR, 1, TIME '23:00:00') AS T;
......
......@@ -4,14 +4,14 @@
--
CALL PARSEDATETIME('3. Februar 2001', 'd. MMMM yyyy', 'de');
> TIMESTAMP '2001-02-03 00:00:00.0'
> ---------------------------------
> 2001-02-03 00:00:00.0
> TIMESTAMP '2001-02-03 00:00:00'
> -------------------------------
> 2001-02-03 00:00:00
> rows: 1
CALL PARSEDATETIME('02/03/2001 04:05:06', 'MM/dd/yyyy HH:mm:ss');
> TIMESTAMP '2001-02-03 04:05:06.0'
> ---------------------------------
> 2001-02-03 04:05:06.0
> TIMESTAMP '2001-02-03 04:05:06'
> -------------------------------
> 2001-02-03 04:05:06
> rows: 1
......@@ -5,24 +5,24 @@
select trunc('2015-05-29 15:00:00') R;
> R
> ---------------------
> 2015-05-29 00:00:00.0
> -------------------
> 2015-05-29 00:00:00
> rows: 1
select trunc('2015-05-29') R;
> R
> ---------------------
> 2015-05-29 00:00:00.0
> -------------------
> 2015-05-29 00:00:00
> rows: 1
select trunc(timestamp '2000-01-01 10:20:30.0') R;
> R
> ---------------------
> 2000-01-01 00:00:00.0
> -------------------
> 2000-01-01 00:00:00
> rows: 1
select trunc(timestamp '2001-01-01 14:00:00.0') R;
> R
> ---------------------
> 2001-01-01 00:00:00.0
> -------------------
> 2001-01-01 00:00:00
> rows: 1
......@@ -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;
> D YEAR(D) EXTRACT(YEAR FROM D) CAST(D AS TIMESTAMP)
> ---------- ------- -------------------- ---------------------
> -1-01-01 -1 -1 -1-01-01 00:00:00.0
> 0-01-01 0 0 0-01-01 00:00:00.0
> 0001-01-01 1 1 0001-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
> 0001-01-01 1 1 0001-01-01 00:00:00
> rows: 3
drop table p;
......@@ -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';
> ID D
> -- ---------------------
> 1 1999-12-01 23:59:00.0
> -- -------------------
> 1 1999-12-01 23:59:00
> rows: 1
select * from test where d= timestamp '2006-01-01 12:00:00.000';
> ID D
> -- ---------------------
> 1 2006-01-01 12:00:00.0
> -- -------------------
> 1 2006-01-01 12:00:00
> rows: 1
drop table test;
......@@ -2684,9 +2684,9 @@ select x/10 y from system_range(1, 100) group by x/10;
> rows: 11
select timestamp '2001-02-03T10:30:33';
> TIMESTAMP '2001-02-03 10:30:33.0'
> ---------------------------------
> 2001-02-03 10:30:33.0
> TIMESTAMP '2001-02-03 10:30:33'
> -------------------------------
> 2001-02-03 10:30:33
> rows: 1
CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255));
......@@ -6884,7 +6884,7 @@ DROP TABLE TEST;
> ok
--- 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
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);
SELECT * FROM TEST;
> ID XT XD XTS
> ---- -------- ---------- -----------------------------
> 0 00:00:00 0001-02-03 0002-03-04 00:00:00.0
> 1 01:02:03 0004-05-06 0007-08-09 00:01:02.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
> 2 23:59:59 1999-12-31 1999-12-31 23:59:59.123456789
> null null null null
> rows: 4
......@@ -6927,24 +6927,24 @@ SELECT XD+1, XD-1, XD-XD FROM TEST;
> rows: 4
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;
> 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
> 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
> 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
> null null null null null null null
> 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 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 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 1999-12-31 00:00:00
> null null null null null null null
> rows: 4
SCRIPT SIMPLE NOPASSWORDS NOSETTINGS;
> SCRIPT
> ----------------------------------------------------------------------------------------------------------------------------------
> -- 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;
> 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(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');
> 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);
> 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
> update count: 1
select * from test;
> 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
> ID T0 T1 T2 T5
> -- ------------------- --------------------- ---------------------- -------------------------
> 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
DROP TABLE IF EXISTS TEST;
......
......@@ -1235,7 +1235,7 @@ public class TestMVTableEngine extends TestBase {
assertEquals(3d, rs.getFloat(10));
assertEquals("10:00:00", rs.getString(11));
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("00000000-0000-0000-0000-000000000000",
rs.getString(15));
......@@ -1254,7 +1254,7 @@ public class TestMVTableEngine extends TestBase {
assertEquals(32d, rs.getFloat(10));
assertEquals("10:00:00", rs.getString(11));
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("00000000-0000-0000-0000-000000000000",
rs.getString(15));
......@@ -1274,7 +1274,7 @@ public class TestMVTableEngine extends TestBase {
assertEquals(0.0d, rs.getFloat(10));
assertEquals("10:00:00", rs.getString(11));
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("00000000-0000-0000-0000-000000000000",
rs.getString(15));
......@@ -1293,7 +1293,7 @@ public class TestMVTableEngine extends TestBase {
assertEquals(1.0d, rs.getFloat(10));
assertEquals("10:00:00", rs.getString(11));
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("00000000-0000-0000-0000-000000000000",
rs.getString(15));
......
......@@ -97,11 +97,11 @@ public class TestDate extends TestBase {
// can't convert using java.util.Date
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").
convertTo(Value.TIMESTAMP).getString());
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").
convertTo(Value.TIMESTAMP).getString());
assertEquals(
......@@ -163,8 +163,9 @@ public class TestDate extends TestBase {
assertEquals(Value.TIME, t1.getType());
long nanos = t1.getNanos();
assertEquals((int) ((nanos >>> 32) ^ nanos), t1.hashCode());
assertEquals(t1.getString().length(), t1.getDisplaySize());
assertEquals(ValueTime.PRECISION, t1.getPrecision());
// Literals return maximum precision
assertEquals(ValueTime.MAXIMUM_PRECISION, t1.getDisplaySize());
assertEquals(ValueTime.MAXIMUM_PRECISION, t1.getPrecision());
assertEquals("java.sql.Time", t1.getObject().getClass().getName());
ValueTime t1b = ValueTime.parse("11:11:11");
assertTrue(t1 == t1b);
......@@ -220,7 +221,7 @@ public class TestDate extends TestBase {
@SuppressWarnings("unlikely-arg-type")
private void testValueTimestamp() {
assertEquals(
"2001-02-03 04:05:06.0", ValueTimestamp.get(
"2001-02-03 04:05:06", ValueTimestamp.get(
Timestamp.valueOf(
"2001-02-03 04:05:06")).getString());
assertEquals(
......@@ -228,9 +229,9 @@ public class TestDate extends TestBase {
Timestamp.valueOf(
"2001-02-03 04:05:06.001002003")).getString());
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(
"9999-12-31 23:59:59.0",
"9999-12-31 23:59:59",
ValueTimestamp.parse(
"9999-12-31 23:59:59").getString());
......@@ -257,9 +258,10 @@ public class TestDate extends TestBase {
assertEquals((int) ((dateValue >>> 32) ^ dateValue ^
(nanos >>> 32) ^ nanos),
t1.hashCode());
assertEquals(t1.getString().length(), t1.getDisplaySize());
assertEquals(ValueTimestamp.PRECISION, t1.getPrecision());
assertEquals(10, t1.getScale());
// Literals return maximum precision
assertEquals(ValueTimestamp.MAXIMUM_PRECISION, t1.getDisplaySize());
assertEquals(ValueTimestamp.MAXIMUM_PRECISION, t1.getPrecision());
assertEquals(9, t1.getScale());
assertEquals("java.sql.Timestamp", t1.getObject().getClass().getName());
ValueTimestamp t1b = ValueTimestamp.parse("2001-01-01 01:01:01.111");
assertTrue(t1 == t1b);
......@@ -299,7 +301,7 @@ public class TestDate extends TestBase {
t1.convertScale(true, 2).getString());
assertEquals("2001-01-01 01:01:01.1",
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 = ValueTimestamp.parse("-2001-01-01 01:01:01.123456789");
assertEquals("-2001-01-01 01:01:01.123457",
......@@ -308,24 +310,24 @@ public class TestDate extends TestBase {
assertFalse(ValueTimestamp.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(
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(
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(
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(
ValueTime.parse("10:10:10")).getString());
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(
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(
ValueTime.parse("24:10:10")).getString());
}
......
......@@ -46,6 +46,7 @@ public class TestDateTimeUtils extends TestBase {
testWeekOfYear();
testDateValueFromDenormalizedDate();
testUTC2Value(false);
testConvertScale();
}
private void testParseTimeNanosDB2Format() {
......@@ -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 {
private void test1() throws SQLException {
Connection conn = getConnection(getTestName());
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')");
// 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')");
......@@ -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')");
ResultSet rs = stat.executeQuery("select t1 from test");
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);
assertEquals(1970, ts.getYear());
assertEquals(1, ts.getMonth());
......@@ -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')");
ResultSet rs = stat.executeQuery("select t1 from test_order order by t1");
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();
}
......
......@@ -764,7 +764,7 @@ public class TestTools extends TestBase {
assertEquals(new byte[] { (byte) 10, (byte) 20 }, rs.getBytes("f"));
assertEquals("2007-12-31", rs.getString("g"));
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());
conn.close();
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论