提交 e1a20588 authored 作者: thomasmueller's avatar thomasmueller

Merge branch 'master' of https://github.com/h2database/h2database

......@@ -5,6 +5,7 @@
*/
package org.h2.engine;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashMap;
......@@ -13,7 +14,6 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Random;
import java.util.ArrayDeque;
import java.util.concurrent.TimeUnit;
import org.h2.api.ErrorCode;
import org.h2.command.Command;
......@@ -1714,6 +1714,11 @@ public class Session extends SessionWithState {
if (v.getType() != Value.CLOB && v.getType() != Value.BLOB) {
return;
}
// issue #790: why are temporary LOBs showing up on the system session?
if (SysProperties.CHECK && id == 1) {
throw DbException.throwInternalError(
"the system session is not supposed to be creating temporary LOBs");
}
if (v.getTableId() == LobStorageFrontend.TABLE_RESULT ||
v.getTableId() == LobStorageFrontend.TABLE_TEMP) {
if (temporaryResultLobs == null) {
......
......@@ -837,28 +837,22 @@ public class Function extends Expression implements FunctionCall {
break;
}
case DAY_OF_MONTH:
result = ValueInt.get(DateTimeUtils.getDatePart(v0.getDate(),
Calendar.DAY_OF_MONTH));
result = ValueInt.get(DateTimeUtils.getDatePart(v0, Calendar.DAY_OF_MONTH));
break;
case DAY_OF_WEEK:
result = ValueInt.get(DateTimeUtils.getDatePart(v0.getDate(),
Calendar.DAY_OF_WEEK));
result = ValueInt.get(DateTimeUtils.getDatePart(v0, Calendar.DAY_OF_WEEK));
break;
case DAY_OF_YEAR:
result = ValueInt.get(DateTimeUtils.getDatePart(v0.getDate(),
Calendar.DAY_OF_YEAR));
result = ValueInt.get(DateTimeUtils.getDatePart(v0, Calendar.DAY_OF_YEAR));
break;
case HOUR:
result = ValueInt.get(DateTimeUtils.getDatePart(v0.getTimestamp(),
Calendar.HOUR_OF_DAY));
result = ValueInt.get(DateTimeUtils.getDatePart(v0, Calendar.HOUR_OF_DAY));
break;
case MINUTE:
result = ValueInt.get(DateTimeUtils.getDatePart(v0.getTimestamp(),
Calendar.MINUTE));
result = ValueInt.get(DateTimeUtils.getDatePart(v0, Calendar.MINUTE));
break;
case MONTH:
result = ValueInt.get(DateTimeUtils.getDatePart(v0.getDate(),
Calendar.MONTH));
result = ValueInt.get(DateTimeUtils.getDatePart(v0, Calendar.MONTH));
break;
case MONTH_NAME: {
SimpleDateFormat monthName = new SimpleDateFormat("MMMM",
......@@ -868,29 +862,25 @@ public class Function extends Expression implements FunctionCall {
break;
}
case QUARTER:
result = ValueInt.get((DateTimeUtils.getDatePart(v0.getDate(),
Calendar.MONTH) - 1) / 3 + 1);
result = ValueInt.get((DateTimeUtils.getDatePart(v0, Calendar.MONTH) - 1) / 3 + 1);
break;
case SECOND:
result = ValueInt.get(DateTimeUtils.getDatePart(v0.getTimestamp(),
Calendar.SECOND));
result = ValueInt.get(DateTimeUtils.getDatePart(v0, Calendar.SECOND));
break;
case WEEK:
result = ValueInt.get(DateTimeUtils.getDatePart(v0.getDate(),
Calendar.WEEK_OF_YEAR));
result = ValueInt.get(DateTimeUtils.getDatePart(v0, Calendar.WEEK_OF_YEAR));
break;
case YEAR:
result = ValueInt.get(DateTimeUtils.getDatePart(v0.getDate(),
Calendar.YEAR));
result = ValueInt.get(DateTimeUtils.getDatePart(v0, Calendar.YEAR));
break;
case ISO_YEAR:
result = ValueInt.get(DateTimeUtils.getIsoYear(v0.getDate()));
result = ValueInt.get(DateTimeUtils.getIsoYear(v0));
break;
case ISO_WEEK:
result = ValueInt.get(DateTimeUtils.getIsoWeek(v0.getDate()));
result = ValueInt.get(DateTimeUtils.getIsoWeek(v0));
break;
case ISO_DAY_OF_WEEK:
result = ValueInt.get(DateTimeUtils.getIsoDayOfWeek(v0.getDate()));
result = ValueInt.get(DateTimeUtils.getIsoDayOfWeek(v0));
break;
case CURDATE:
case CURRENT_DATE: {
......@@ -1523,8 +1513,7 @@ public class Function extends Expression implements FunctionCall {
break;
case EXTRACT: {
int field = getDatePart(v0.getString());
result = ValueInt.get(DateTimeUtils.getDatePart(
v1.getTimestamp(), field));
result = ValueInt.get(DateTimeUtils.getDatePart(v1, field));
break;
}
case FORMATDATETIME: {
......
......@@ -125,7 +125,7 @@ public class JdbcBlob extends TraceObject implements Blob {
}
/**
* [Not supported] Sets some bytes of the object.
* Sets some bytes of the object.
*
* @param pos the write position
* @param bytes the bytes to set
......@@ -136,7 +136,19 @@ public class JdbcBlob extends TraceObject implements Blob {
@Override
public int setBytes(long pos, byte[] bytes, int offset, int len)
throws SQLException {
throw unsupported("LOB update");
try {
if (isDebugEnabled()) {
debugCode("setBytes(" + pos + ", " + quoteBytes(bytes) + ", " + offset + ", " + len + ");");
}
checkClosed();
if (pos != 1) {
throw DbException.getInvalidValueException("pos", pos);
}
value = conn.createBlob(new ByteArrayInputStream(bytes, offset, len), -1);
return (int) value.getPrecision();
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
......
......@@ -21,6 +21,7 @@ import org.h2.api.ErrorCode;
import org.h2.engine.Constants;
import org.h2.message.DbException;
import org.h2.message.TraceObject;
import org.h2.store.RangeReader;
import org.h2.util.IOUtils;
import org.h2.util.Task;
import org.h2.value.Value;
......@@ -227,12 +228,34 @@ public class JdbcClob extends TraceObject implements NClob
}
/**
* [Not supported] Sets a substring.
* Fills the Clob. This is only supported for new, empty Clob objects that
* were created with Connection.createClob() or createNClob(). The position
* must be 1, meaning the whole Clob data is set.
*
* @param pos where to start writing (the first character is at position 1)
* @param str the string to add
* @param offset the string offset
* @param len the number of characters to read
* @return the length of the added text
*/
@Override
public int setString(long pos, String str, int offset, int len)
throws SQLException {
throw unsupported("LOB update");
try {
if (isDebugEnabled()) {
debugCode("setString(" + pos + ", " + quote(str) + ", " + offset + ", " + len + ");");
}
checkClosed();
if (pos != 1) {
throw DbException.getInvalidValueException("pos", pos);
} else if (str == null) {
throw DbException.getInvalidValueException("str", str);
}
value = conn.createClob(new RangeReader(new StringReader(str), offset, len), -1);
return (int) value.getPrecision();
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
......
......@@ -21,6 +21,7 @@ import org.h2.value.ValueDate;
import org.h2.value.ValueNull;
import org.h2.value.ValueTime;
import org.h2.value.ValueTimestamp;
import org.h2.value.ValueTimestampTimeZone;
/**
* This utility class contains time conversion functions.
......@@ -317,6 +318,30 @@ public class DateTimeUtils {
return ValueTimestamp.fromDateValueAndNanos(dateValue, nanos);
}
private static Calendar valueToCalendar(Value value) {
Calendar cal;
if (value instanceof ValueTimestamp) {
cal = createGregorianCalendar();
cal.setTime(value.getTimestamp());
} else if (value instanceof ValueDate) {
cal = createGregorianCalendar();
cal.setTime(value.getDate());
} else if (value instanceof ValueTime) {
cal = createGregorianCalendar();
cal.setTime(value.getTime());
} else if (value instanceof ValueTimestampTimeZone) {
ValueTimestampTimeZone v = (ValueTimestampTimeZone) value;
cal = createGregorianCalendar(v.getTimeZone());
cal.setTimeInMillis(DateTimeUtils.convertDateValueToMillis(DateTimeUtils.UTC, v.getDateValue())
+ v.getTimeNanos() / 1000000L
- v.getTimeZoneOffsetMins() * 60000);
} else {
cal = createGregorianCalendar();
cal.setTime(value.getTimestamp());
}
return cal;
}
/**
* Parse a date string. The format is: [+|-]year-month-day
*
......@@ -494,13 +519,12 @@ public class DateTimeUtils {
* Get the specified field of a date, however with years normalized to
* positive or negative, and month starting with 1.
*
* @param d the date
* @param date the date value
* @param field the field type
* @return the value
*/
public static int getDatePart(java.util.Date d, int field) {
Calendar c = getCalendar();
c.setTime(d);
public static int getDatePart(Value date, int field) {
Calendar c = valueToCalendar(date);
if (field == Calendar.YEAR) {
return getYear(c);
}
......@@ -552,13 +576,11 @@ public class DateTimeUtils {
* starts at Monday. See also http://en.wikipedia.org/wiki/ISO_8601
*
* @author Robert Rathsack
* @param date the date object which day of week should be calculated
* @param value the date object which day of week should be calculated
* @return the day of the week, Monday as 1 to Sunday as 7
*/
public static int getIsoDayOfWeek(java.util.Date date) {
Calendar cal = DateTimeUtils.createGregorianCalendar();
cal.setTimeInMillis(date.getTime());
int val = cal.get(Calendar.DAY_OF_WEEK) - 1;
public static int getIsoDayOfWeek(Value value) {
int val = valueToCalendar(value).get(Calendar.DAY_OF_WEEK) - 1;
return val == 0 ? 7 : val;
}
......@@ -573,12 +595,11 @@ public class DateTimeUtils {
* the December 28th always belongs to the last week.
*
* @author Robert Rathsack
* @param date the date object which week of year should be calculated
* @param value the date object which week of year should be calculated
* @return the week of the year
*/
public static int getIsoWeek(java.util.Date date) {
Calendar c = DateTimeUtils.createGregorianCalendar();
c.setTimeInMillis(date.getTime());
public static int getIsoWeek(Value value) {
Calendar c = valueToCalendar(value);
c.setFirstDayOfWeek(Calendar.MONDAY);
c.setMinimalDaysInFirstWeek(4);
return c.get(Calendar.WEEK_OF_YEAR);
......@@ -588,12 +609,11 @@ public class DateTimeUtils {
* Returns the year according to the ISO week definition.
*
* @author Robert Rathsack
* @param date the date object which year should be calculated
* @param value the date object which year should be calculated
* @return the year
*/
public static int getIsoYear(java.util.Date date) {
Calendar cal = DateTimeUtils.createGregorianCalendar();
cal.setTimeInMillis(date.getTime());
public static int getIsoYear(Value value) {
Calendar cal = valueToCalendar(value);
cal.setFirstDayOfWeek(Calendar.MONDAY);
cal.setMinimalDaysInFirstWeek(4);
int year = getYear(cal);
......
......@@ -5,6 +5,7 @@
*/
package org.h2.util;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.management.LockInfo;
......@@ -65,7 +66,7 @@ public class ThreadDeadlockDetector {
return;
}
dumpThreadsAndLocks("ThreadDeadlockDetector - deadlock found :",
threadBean, deadlockedThreadIds);
threadBean, deadlockedThreadIds, System.out);
}
/**
......@@ -74,13 +75,22 @@ public class ThreadDeadlockDetector {
* @param msg the message
*/
public static void dumpAllThreadsAndLocks(String msg) {
dumpAllThreadsAndLocks(msg, System.out);
}
/**
* Dump all deadlocks (if any).
*
* @param msg the message
*/
public static void dumpAllThreadsAndLocks(String msg, PrintStream out) {
final ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
final long[] allThreadIds = threadBean.getAllThreadIds();
dumpThreadsAndLocks(msg, threadBean, allThreadIds);
dumpThreadsAndLocks(msg, threadBean, allThreadIds, out);
}
private static void dumpThreadsAndLocks(String msg, ThreadMXBean threadBean,
long[] threadIds) {
long[] threadIds, PrintStream out) {
final StringWriter stringWriter = new StringWriter();
final PrintWriter print = new PrintWriter(stringWriter);
......@@ -115,7 +125,8 @@ public class ThreadDeadlockDetector {
print.flush();
// Dump it to system.out in one block, so it doesn't get mixed up with
// other stuff when we're using a logging subsystem.
System.out.println(stringWriter.getBuffer());
out.println(stringWriter.getBuffer());
out.flush();
}
private static void printThreadInfo(PrintWriter print, ThreadInfo ti) {
......
......@@ -9,6 +9,7 @@ import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.SimpleTimeZone;
import java.util.TimeZone;
import org.h2.api.ErrorCode;
import org.h2.api.TimestampWithTimeZone;
......@@ -50,7 +51,8 @@ public class ValueTimestampTimeZone extends Value {
*/
private final long timeNanos;
/**
* Time zone offset from UTC in minutes, range of -12hours to +12hours
* Time zone offset from UTC in minutes, range of -18 hours to +18 hours. This
* range is compatible with OffsetDateTime from JSR-310.
*/
private final short timeZoneOffsetMins;
......@@ -60,8 +62,13 @@ public class ValueTimestampTimeZone extends Value {
throw new IllegalArgumentException(
"timeNanos out of range " + timeNanos);
}
if (timeZoneOffsetMins < (-12 * 60)
|| timeZoneOffsetMins >= (12 * 60)) {
/*
* Some current and historic time zones have offsets larger than 12 hours.
* JSR-310 determines 18 hours as maximum possible offset in both directions, so
* we use this limit too for compatibility.
*/
if (timeZoneOffsetMins < (-18 * 60)
|| timeZoneOffsetMins > (18 * 60)) {
throw new IllegalArgumentException(
"timeZoneOffsetMins out of range " + timeZoneOffsetMins);
}
......@@ -201,6 +208,19 @@ public class ValueTimestampTimeZone extends Value {
return timeZoneOffsetMins;
}
/**
* Returns compatible offset-based time zone with no DST schedule.
*
* @return compatible offset-based time zone
*/
public TimeZone getTimeZone() {
int offset = timeZoneOffsetMins;
if (offset == 0) {
return DateTimeUtils.UTC;
}
return new SimpleTimeZone(offset * 60000, Integer.toString(offset));
}
@Override
public Timestamp getTimestamp() {
throw new UnsupportedOperationException("unimplemented");
......
......@@ -86,8 +86,6 @@ public class TestLobApi extends TestBase {
truncate(0);
assertThrows(ErrorCode.FEATURE_NOT_SUPPORTED_1, clob).
setAsciiStream(1);
assertThrows(ErrorCode.FEATURE_NOT_SUPPORTED_1, clob).
setString(1, "", 0, 1);
assertThrows(ErrorCode.FEATURE_NOT_SUPPORTED_1, clob).
position("", 0);
assertThrows(ErrorCode.FEATURE_NOT_SUPPORTED_1, clob).
......@@ -96,8 +94,6 @@ public class TestLobApi extends TestBase {
Blob blob = rs.getBlob(3);
assertThrows(ErrorCode.FEATURE_NOT_SUPPORTED_1, blob).
truncate(0);
assertThrows(ErrorCode.FEATURE_NOT_SUPPORTED_1, blob).
setBytes(1, new byte[0], 0, 0);
assertThrows(ErrorCode.FEATURE_NOT_SUPPORTED_1, blob).
position(new byte[1], 0);
assertThrows(ErrorCode.FEATURE_NOT_SUPPORTED_1, blob).
......@@ -237,30 +233,43 @@ public class TestLobApi extends TestBase {
prep.setInt(1, 2);
b = conn.createBlob();
b.setBytes(1, data);
assertEquals(length, b.setBytes(1, data));
prep.setBlob(2, b);
prep.execute();
prep.setInt(1, 3);
prep.setBlob(2, new ByteArrayInputStream(data));
Blob b2 = conn.createBlob();
byte[] xdata = new byte[length + 2];
System.arraycopy(data, 0, xdata, 1, length);
assertEquals(length, b2.setBytes(1, xdata, 1, length));
prep.setBlob(2, b2);
prep.execute();
prep.setInt(1, 4);
prep.setBlob(2, new ByteArrayInputStream(data));
prep.execute();
prep.setInt(1, 5);
prep.setBlob(2, new ByteArrayInputStream(data), -1);
prep.execute();
ResultSet rs;
rs = stat.executeQuery("select * from test");
rs.next();
Blob b2 = rs.getBlob(2);
assertEquals(length, b2.length());
Blob b3 = rs.getBlob(2);
assertEquals(length, b3.length());
byte[] bytes = b.getBytes(1, length);
byte[] bytes2 = b2.getBytes(1, length);
byte[] bytes2 = b3.getBytes(1, length);
assertEquals(bytes, bytes2);
rs.next();
b3 = rs.getBlob(2);
assertEquals(length, b3.length());
bytes2 = b3.getBytes(1, length);
assertEquals(bytes, bytes2);
rs.next();
b2 = rs.getBlob(2);
assertEquals(length, b2.length());
bytes2 = b2.getBytes(1, length);
b3 = rs.getBlob(2);
assertEquals(length, b3.length());
bytes2 = b3.getBytes(1, length);
assertEquals(bytes, bytes2);
while (rs.next()) {
bytes2 = rs.getBytes(2);
......@@ -311,20 +320,28 @@ public class TestLobApi extends TestBase {
NClob nc;
nc = conn.createNClob();
nc.setString(1, new String(data));
assertEquals(length, nc.setString(1, new String(data)));
prep.setInt(1, 5);
prep.setNClob(2, nc);
prep.execute();
prep.setInt(1, 5);
nc = conn.createNClob();
char[] xdata = new char[length + 2];
System.arraycopy(data, 0, xdata, 1, length);
assertEquals(length, nc.setString(1, new String(xdata), 1, length));
prep.setInt(1, 6);
prep.setNClob(2, nc);
prep.execute();
prep.setInt(1, 7);
prep.setNClob(2, new StringReader(new String(data)));
prep.execute();
prep.setInt(1, 6);
prep.setInt(1, 8);
prep.setNClob(2, new StringReader(new String(data)), -1);
prep.execute();
prep.setInt(1, 7);
prep.setInt(1, 9);
prep.setNString(2, new String(data));
prep.execute();
......
......@@ -20,3 +20,87 @@ select dateadd('year', -1, timestamp '2000-02-29 10:20:30.012345678') d1 from te
> -----------------------------
> 1999-02-28 10:20:30.012345678
> rows: 1
drop table test;
> ok
create table test(d date, t time, ts timestamp);
> ok
insert into test values(date '2001-01-01', time '01:00:00', timestamp '2010-01-01 00:00:00');
> update count: 1
select ts + t x from test;
> X
> ---------------------
> 2010-01-01 01:00:00.0
> rows: 1
select ts + t + t - t x from test;
> X
> ---------------------
> 2010-01-01 01:00:00.0
> rows: 1
select ts + t * 0.5 x from test;
> X
> ---------------------
> 2010-01-01 00:30:00.0
> rows: 1
select ts + 0.5 x from test;
> X
> ---------------------
> 2010-01-01 12:00:00.0
> rows: 1
select ts - 1.5 x from test;
> X
> ---------------------
> 2009-12-30 12:00:00.0
> rows: 1
select ts + 0.5 * t + t - t x from test;
> X
> ---------------------
> 2010-01-01 00:30:00.0
> rows: 1
select ts + t / 0.5 x from test;
> X
> ---------------------
> 2010-01-01 02:00:00.0
> 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
> 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 00:00:00.0 2000-12-31 00:00:00.0 2010-01-05 00:00:00.0 2009-12-30 00:00:00.0
> rows: 1
select 1 + d + t + 1 from test;
> DATEADD('DAY', 1, (T + DATEADD('DAY', 1, D)))
> ---------------------------------------------
> 2001-01-03 01:00:00.0
> rows: 1
select ts - t - 2 from test;
> DATEADD('DAY', -2, (TS - T))
> ----------------------------
> 2009-12-29 23:00:00.0
> rows: 1
drop table test;
> ok
call dateadd('MS', 1, TIMESTAMP '2001-02-03 04:05:06.789001');
> TIMESTAMP '2001-02-03 04:05:06.790001'
> --------------------------------------
> 2001-02-03 04:05:06.790001
> rows: 1
......@@ -93,3 +93,68 @@ select datediff('millisecond', timestamp '2004-01-01 10:00:00.5', timestamp '200
> 500
> rows: 1
SELECT DATEDIFF('SECOND', '1900-01-01 00:00:00.001', '1900-01-01 00:00:00.002'), DATEDIFF('SECOND', '2000-01-01 00:00:00.001', '2000-01-01 00:00:00.002');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('SECOND', '1900-01-01 00:00:00.000', '1900-01-01 00:00:00.001'), DATEDIFF('SECOND', '2000-01-01 00:00:00.000', '2000-01-01 00:00:00.001');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('MINUTE', '1900-01-01 00:00:00.000', '1900-01-01 00:00:01.000'), DATEDIFF('MINUTE', '2000-01-01 00:00:00.000', '2000-01-01 00:00:01.000');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('MINUTE', '1900-01-01 00:00:01.000', '1900-01-01 00:00:02.000'), DATEDIFF('MINUTE', '2000-01-01 00:00:01.000', '2000-01-01 00:00:02.000');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('HOUR', '1900-01-01 00:00:00.000', '1900-01-01 00:00:01.000'), DATEDIFF('HOUR', '2000-01-01 00:00:00.000', '2000-01-01 00:00:01.000');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('HOUR', '1900-01-01 00:00:00.001', '1900-01-01 00:00:01.000'), DATEDIFF('HOUR', '2000-01-01 00:00:00.001', '2000-01-01 00:00:01.000');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('HOUR', '1900-01-01 01:00:00.000', '1900-01-01 01:00:01.000'), DATEDIFF('HOUR', '2000-01-01 01:00:00.000', '2000-01-01 01:00:01.000');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('HOUR', '1900-01-01 01:00:00.001', '1900-01-01 01:00:01.000'), DATEDIFF('HOUR', '2000-01-01 01:00:00.001', '2000-01-01 01:00:01.000');
> 0 0
> - -
> 0 0
> rows: 1
select datediff(day, '2015-12-09 23:59:00.0', '2016-01-16 23:59:00.0'), datediff(wk, '2015-12-09 23:59:00.0', '2016-01-16 23:59:00.0');
> 38 5
> -- -
> 38 5
> rows: 1
call datediff('MS', TIMESTAMP '2001-02-03 04:05:06.789001', TIMESTAMP '2001-02-03 04:05:06.789002');
> 0
> -
> 0
> rows: 1
call datediff('MS', TIMESTAMP '1900-01-01 00:00:01.000', TIMESTAMP '2008-01-01 00:00:00.000');
> 3408134399000
> -------------
> 3408134399000
> rows: 1
......@@ -14,3 +14,22 @@ select dayofmonth(date '2005-09-12') d12 from test;
> ---
> 12
> rows: 1
drop table test;
> ok
create table test(ts timestamp with time zone);
> ok
insert into test(ts) values ('2010-05-11 00:00:00+10:00'), ('2010-05-11 00:00:00-10:00');
> update count: 2
select dayofmonth(ts) d from test;
> D
> --
> 11
> 11
> rows: 2
drop table test;
> ok
......@@ -14,3 +14,22 @@ select hour(time '23:10:59') d23 from test;
> ---
> 23
> rows: 1
drop table test;
> ok
create table test(ts timestamp with time zone);
> ok
insert into test(ts) values ('2010-05-11 05:15:10+10:00'), ('2010-05-11 05:15:10-10:00');
> update count: 2
select hour(ts) h from test;
> H
> -
> 5
> 5
> rows: 2
drop table test;
> ok
......@@ -557,81 +557,6 @@ explain select * from test limit 10 sample_size 10;
drop table test;
> ok
create table test(d date, t time, ts timestamp);
> ok
insert into test values(date '2001-01-01', time '01:00:00', timestamp '2010-01-01 00:00:00');
> update count: 1
select ts + t x from test;
> X
> ---------------------
> 2010-01-01 01:00:00.0
> rows: 1
select ts + t + t - t x from test;
> X
> ---------------------
> 2010-01-01 01:00:00.0
> rows: 1
select ts + t * 0.5 x from test;
> X
> ---------------------
> 2010-01-01 00:30:00.0
> rows: 1
select ts + 0.5 x from test;
> X
> ---------------------
> 2010-01-01 12:00:00.0
> rows: 1
select ts - 1.5 x from test;
> X
> ---------------------
> 2009-12-30 12:00:00.0
> rows: 1
select ts + 0.5 * t + t - t x from test;
> X
> ---------------------
> 2010-01-01 00:30:00.0
> rows: 1
select ts + t / 0.5 x from test;
> X
> ---------------------
> 2010-01-01 02:00:00.0
> 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
> 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 00:00:00.0 2000-12-31 00:00:00.0 2010-01-05 00:00:00.0 2009-12-30 00:00:00.0
> rows: 1
select 1 + d + t + 1 from test;
> DATEADD('DAY', 1, (T + DATEADD('DAY', 1, D)))
> ---------------------------------------------
> 2001-01-03 01:00:00.0
> rows: 1
select ts - t - 2 from test;
> DATEADD('DAY', -2, (TS - T))
> ----------------------------
> 2009-12-29 23:00:00.0
> rows: 1
drop table test;
> ok
create table test(id int primary key);
> ok
......@@ -3904,60 +3829,6 @@ SELECT CASE WHEN NOT (false IN (null)) THEN false END;
> null
> rows: 1
SELECT DATEDIFF('SECOND', '1900-01-01 00:00:00.001', '1900-01-01 00:00:00.002'), DATEDIFF('SECOND', '2000-01-01 00:00:00.001', '2000-01-01 00:00:00.002');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('SECOND', '1900-01-01 00:00:00.000', '1900-01-01 00:00:00.001'), DATEDIFF('SECOND', '2000-01-01 00:00:00.000', '2000-01-01 00:00:00.001');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('MINUTE', '1900-01-01 00:00:00.000', '1900-01-01 00:00:01.000'), DATEDIFF('MINUTE', '2000-01-01 00:00:00.000', '2000-01-01 00:00:01.000');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('MINUTE', '1900-01-01 00:00:01.000', '1900-01-01 00:00:02.000'), DATEDIFF('MINUTE', '2000-01-01 00:00:01.000', '2000-01-01 00:00:02.000');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('HOUR', '1900-01-01 00:00:00.000', '1900-01-01 00:00:01.000'), DATEDIFF('HOUR', '2000-01-01 00:00:00.000', '2000-01-01 00:00:01.000');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('HOUR', '1900-01-01 00:00:00.001', '1900-01-01 00:00:01.000'), DATEDIFF('HOUR', '2000-01-01 00:00:00.001', '2000-01-01 00:00:01.000');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('HOUR', '1900-01-01 01:00:00.000', '1900-01-01 01:00:01.000'), DATEDIFF('HOUR', '2000-01-01 01:00:00.000', '2000-01-01 01:00:01.000');
> 0 0
> - -
> 0 0
> rows: 1
SELECT DATEDIFF('HOUR', '1900-01-01 01:00:00.001', '1900-01-01 01:00:01.000'), DATEDIFF('HOUR', '2000-01-01 01:00:00.001', '2000-01-01 01:00:01.000');
> 0 0
> - -
> 0 0
> rows: 1
select datediff(day, '2015-12-09 23:59:00.0', '2016-01-16 23:59:00.0'), datediff(wk, '2015-12-09 23:59:00.0', '2016-01-16 23:59:00.0');
> 38 5
> -- -
> 38 5
> rows: 1
create table test(id int);
> ok
......@@ -3972,30 +3843,12 @@ insert into test values(1), (2), (3), (4);
drop table test;
> ok
call datediff('MS', TIMESTAMP '2001-02-03 04:05:06.789001', TIMESTAMP '2001-02-03 04:05:06.789002');
> 0
> -
> 0
> rows: 1
call datediff('MS', TIMESTAMP '1900-01-01 00:00:01.000', TIMESTAMP '2008-01-01 00:00:00.000');
> 3408134399000
> -------------
> 3408134399000
> rows: 1
call select 1.0/3.0*3.0, 100.0/2.0, -25.0/100.0, 0.0/3.0, 6.9/2.0, 0.72179425150347250912311550800000 / 5314251955.21;
> SELECT 0.999999999999999999999999990, 50, -0.25, 0, 3.45, 1.35822361752313607260107721120531135706133161972E-10 FROM SYSTEM_RANGE(1, 1) /* PUBLIC.RANGE_INDEX */ /* scanCount: 2 */
> -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
> (0.999999999999999999999999990, 50, -0.25, 0, 3.45, 1.35822361752313607260107721120531135706133161972E-10)
> rows: 1
call dateadd('MS', 1, TIMESTAMP '2001-02-03 04:05:06.789001');
> TIMESTAMP '2001-02-03 04:05:06.790001'
> --------------------------------------
> 2001-02-03 04:05:06.790001
> rows: 1
CALL 1 /* comment */ ;;
> 1
> -
......
......@@ -6,6 +6,7 @@
package org.h2.test.synth;
import java.io.InputStream;
import java.lang.ProcessBuilder.Redirect;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
......@@ -26,6 +27,13 @@ import org.h2.util.New;
*/
public class TestKillRestartMulti extends TestBase {
/**
* We want self-destruct to occur before the read times out and we kill the
* child process.
*/
private static final int CHILD_READ_TIMEOUT_MS = 7 * 60 * 1000; // 7 minutes
private static final int CHILD_SELFDESTRUCT_TIMEOUT_MINS = 5;
private String driver = "org.h2.Driver";
private String url;
private String user = "sa";
......@@ -34,6 +42,25 @@ public class TestKillRestartMulti extends TestBase {
private final ArrayList<String> tables = New.arrayList();
private int openCount;
/**
* Note that this entry can be used in two different ways, either
* (a) running just this test
* (b) or when this test invokes itself in a child process
*/
public static void main(String... args) throws Exception {
if (args != null && args.length > 0) {
// the child process case
SelfDestructor.startCountdown(CHILD_SELFDESTRUCT_TIMEOUT_MINS);
new TestKillRestartMulti().test(args);
}
else
{
// the standalone test case
TestBase.createCaller().init().test();
}
}
@Override
public void test() throws Exception {
if (config.networked) {
......@@ -47,20 +74,22 @@ public class TestKillRestartMulti extends TestBase {
user = getUser();
password = getPassword();
String selfDestruct = SelfDestructor.getPropertyString(60);
String[] procDef = { "java", selfDestruct,
"-cp", getClassPath(),
// Inherit error so that the stacktraces reported from SelfDestructor
// show up in our log.
ProcessBuilder pb = new ProcessBuilder().redirectError(Redirect.INHERIT)
.command("java", selfDestruct, "-cp", getClassPath(),
getClass().getName(), "-url", url, "-user", user,
"-password", password };
"-password", password);
deleteDb("killRestartMulti");
int len = getSize(3, 10);
Random random = new Random();
for (int i = 0; i < len; i++) {
Process p = Runtime.getRuntime().exec(procDef);
Process p = pb.start();
InputStream in = p.getInputStream();
OutputCatcher catcher = new OutputCatcher(in);
catcher.start();
while (true) {
String s = catcher.readLine(5 * 60 * 1000);
String s = catcher.readLine(CHILD_READ_TIMEOUT_MS);
// System.out.println("> " + s);
if (s == null) {
fail("No reply from process");
......@@ -72,14 +101,16 @@ public class TestKillRestartMulti extends TestBase {
Thread.sleep(sleep);
printTime("killing: " + i);
p.destroy();
printTime("killing, waiting for: " + i);
p.waitFor();
printTime("killing, dead: " + i);
break;
} else if (s.startsWith("#Info")) {
// System.out.println("info: " + s);
} else if (s.startsWith("#Fail")) {
System.err.println(s);
while (true) {
String a = catcher.readLine(5 * 60 * 1000);
String a = catcher.readLine(CHILD_READ_TIMEOUT_MS);
if (a == null || "#End".endsWith(a)) {
break;
}
......@@ -121,17 +152,6 @@ public class TestKillRestartMulti extends TestBase {
deleteDb("killRestartMulti");
}
/**
* This method is called when executing this application from the command
* line.
*
* @param args the command line parameters
*/
public static void main(String... args) {
SelfDestructor.startCountdown(60);
new TestKillRestartMulti().test(args);
}
private void test(String... args) {
for (int i = 0; i < args.length; i++) {
if ("-url".equals(args[i])) {
......
......@@ -5,21 +5,26 @@
*/
package org.h2.test.unit;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import static org.h2.util.DateTimeUtils.getIsoDayOfWeek;
import static org.h2.util.DateTimeUtils.getIsoWeek;
import static org.h2.util.DateTimeUtils.getIsoYear;
import org.h2.test.TestBase;
import org.h2.util.DateTimeUtils;
import org.h2.value.Value;
import org.h2.value.ValueDate;
import org.h2.value.ValueTimestamp;
import org.h2.value.ValueTimestampTimeZone;
/**
* Test cases for DateTimeIso8601Utils.
*/
public class TestDateIso8601 extends TestBase {
private final SimpleDateFormat dateFormatter =
new SimpleDateFormat("yyyy-MM-dd");
private enum Type {
DATE, TIMESTAMP, TIMESTAMP_TIMEZONE_0, TIMESTAMP_TIMEZONE_PLUS_18, TIMESTAMP_TIMEZONE_MINUS_18;
}
private static Type type;
/**
* Run just this test.
......@@ -30,8 +35,41 @@ public class TestDateIso8601 extends TestBase {
TestBase.createCaller().init().test();
}
private static Value parse(String s) {
if (type == null) {
throw new IllegalStateException();
}
switch (type) {
case DATE:
return ValueDate.parse(s);
case TIMESTAMP:
return ValueTimestamp.parse(s);
case TIMESTAMP_TIMEZONE_0:
return ValueTimestampTimeZone.parse(s + " 00:00:00.0Z");
case TIMESTAMP_TIMEZONE_PLUS_18:
return ValueTimestampTimeZone.parse(s + " 00:00:00+18:00");
case TIMESTAMP_TIMEZONE_MINUS_18:
return ValueTimestampTimeZone.parse(s + " 00:00:00-18:00");
default:
throw new IllegalStateException();
}
}
@Override
public void test() throws Exception {
type = Type.DATE;
doTest();
type = Type.TIMESTAMP;
doTest();
type = Type.TIMESTAMP_TIMEZONE_0;
doTest();
type = Type.TIMESTAMP_TIMEZONE_PLUS_18;
doTest();
type = Type.TIMESTAMP_TIMEZONE_MINUS_18;
doTest();
}
private void doTest() throws Exception {
testIsoDayOfWeek();
testIsoWeekJanuary1thMonday();
testIsoWeekJanuary1thTuesday();
......@@ -49,14 +87,6 @@ public class TestDateIso8601 extends TestBase {
testIsoYearJanuary1thSunday();
}
private Date parse(String s) throws ParseException {
return dateFormatter.parse(s);
}
private static int getIsoDayOfWeek(Date date) {
return DateTimeUtils.getIsoDayOfWeek(date);
}
/**
* Test if day of week is returned as Monday = 1 to Sunday = 7.
*/
......@@ -70,11 +100,6 @@ public class TestDateIso8601 extends TestBase {
assertEquals(7, getIsoDayOfWeek(parse("2008-10-05")));
}
private static int getIsoWeek(Date date) {
Timestamp ts = new Timestamp(date.getTime());
return DateTimeUtils.getIsoWeek(ts);
}
/**
* January 1st is a Monday therefore the week belongs to the next year.
*/
......@@ -154,11 +179,6 @@ public class TestDateIso8601 extends TestBase {
assertEquals(2, getIsoWeek(parse("2012-01-09")));
}
private static int getIsoYear(Date date) {
Timestamp ts = new Timestamp(date.getTime());
return DateTimeUtils.getIsoYear(ts);
}
/**
* January 1st is a Monday therefore year is equal to isoYear.
*/
......
......@@ -6,7 +6,7 @@
package org.h2.test.utils;
import java.sql.Timestamp;
import java.util.Map;
import org.h2.util.ThreadDeadlockDetector;
/**
* This is a self-destructor class to kill a long running process automatically
......@@ -55,17 +55,8 @@ public class SelfDestructor {
System.out.println(time + " Killing the process after " +
minutes + " minute(s)");
try {
Map<Thread, StackTraceElement[]> map =
Thread.getAllStackTraces();
for (Map.Entry<Thread, StackTraceElement[]> en :
map.entrySet()) {
System.out.println(en.getKey());
for (StackTraceElement el : en.getValue()) {
System.out.println(" " + el);
}
}
System.out.println();
System.out.flush();
ThreadDeadlockDetector.dumpAllThreadsAndLocks(
"SelfDestructor timed out", System.err);
try {
Thread.sleep(1000);
} catch (Exception e) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论