Unverified 提交 5fad0d3b authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov 提交者: GitHub

Merge pull request #1467 from katzyn/interval

Fix subtraction of timestamps
......@@ -21,6 +21,24 @@ Change Log
<h2>Next Version (unreleased)</h2>
<ul>
<li>PR #1467: Fix subtraction of timestamps
</li>
<li>PR #1464: Assorted minor changes in window processing code
</li>
<li>PR #1463: Fix some window aggregates and reduce amount of collecting implementations
</li>
<li>PR #1462: Separate aggregate and window code in some places
</li>
<li>PR #1461: Add WINDOW clause support
</li>
<li>Issue #1427: Scalability problem in MVSpatialIndex
</li>
<li>PR #1459: Improve window clause correctness checks
</li>
<li>PR #1457: Add NTILE(), LEAD() and LAG() window functions
</li>
<li>PR #1456: Add experimental implementation of remaining types of window frames
</li>
<li>PR #1454: Add FIRST_VALUE(), LAST_VALUE(), and NTH_VALUE()
</li>
<li>PR #1453, Issue #1161: Add ROW_NUMBER(), RANK(), DENSE_RANK(), PERCENT_RANK(), and CUME_DIST() window functions
......
......@@ -5,6 +5,11 @@
*/
package org.h2.expression;
import static org.h2.util.DateTimeUtils.NANOS_PER_DAY;
import static org.h2.util.DateTimeUtils.absoluteDayFromDateValue;
import static org.h2.util.DateTimeUtils.dateAndTimeFromValue;
import static org.h2.util.DateTimeUtils.dateTimeToValue;
import static org.h2.util.DateTimeUtils.dateValueFromAbsoluteDay;
import static org.h2.util.IntervalUtils.NANOS_PER_DAY_BI;
import java.math.BigDecimal;
......@@ -17,7 +22,6 @@ import org.h2.message.DbException;
import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.util.DateTimeFunctions;
import org.h2.util.DateTimeUtils;
import org.h2.util.IntervalUtils;
import org.h2.value.DataType;
import org.h2.value.Value;
......@@ -73,6 +77,12 @@ public class IntervalOperation extends Expression {
private Expression left, right;
private int dataType;
private static BigInteger nanosFromValue(Value v) {
long[] a = dateAndTimeFromValue(v);
return BigInteger.valueOf(absoluteDayFromDateValue(a[0])).multiply(NANOS_PER_DAY_BI)
.add(BigInteger.valueOf(a[1]));
}
public IntervalOperation(IntervalOpType opType, Expression left, Expression right) {
this.opType = opType;
this.left = left;
......@@ -161,21 +171,15 @@ public class IntervalOperation extends Expression {
return ValueInterval.from(IntervalQualifier.HOUR_TO_SECOND, negative, diff / 3_600_000_000_000L,
diff % 3_600_000_000_000L);
} else if (lType == Value.DATE && rType == Value.DATE) {
long diff = DateTimeUtils.absoluteDayFromDateValue(((ValueDate) l).getDateValue())
- DateTimeUtils.absoluteDayFromDateValue(((ValueDate) r).getDateValue());
long diff = absoluteDayFromDateValue(((ValueDate) l).getDateValue())
- absoluteDayFromDateValue(((ValueDate) r).getDateValue());
boolean negative = diff < 0;
if (negative) {
diff = -diff;
}
return ValueInterval.from(IntervalQualifier.DAY, negative, diff, 0L);
} else {
long[] a = DateTimeUtils.dateAndTimeFromValue(l);
long[] b = DateTimeUtils.dateAndTimeFromValue(r);
BigInteger bi1 = BigInteger.valueOf(a[0]).multiply(NANOS_PER_DAY_BI)
.add(BigInteger.valueOf(a[1]));
BigInteger bi2 = BigInteger.valueOf(b[0]).multiply(NANOS_PER_DAY_BI)
.add(BigInteger.valueOf(b[1]));
BigInteger diff = bi1.subtract(bi2);
BigInteger diff = nanosFromValue(l).subtract(nanosFromValue(r));
if (lType == Value.TIMESTAMP_TZ || rType == Value.TIMESTAMP_TZ) {
l = l.convertTo(Value.TIMESTAMP_TZ);
r = r.convertTo(Value.TIMESTAMP_TZ);
......@@ -214,14 +218,13 @@ public class IntervalOperation extends Expression {
} else {
BigInteger a2 = IntervalUtils.intervalToAbsolute((ValueInterval) r);
if (lType == Value.DATE) {
BigInteger a1 = BigInteger
.valueOf(DateTimeUtils.absoluteDayFromDateValue(((ValueDate) l).getDateValue()));
BigInteger a1 = BigInteger.valueOf(absoluteDayFromDateValue(((ValueDate) l).getDateValue()));
a2 = a2.divide(NANOS_PER_DAY_BI);
BigInteger n = opType == IntervalOpType.DATETIME_PLUS_INTERVAL ? a1.add(a2) : a1.subtract(a2);
return ValueDate.fromDateValue(DateTimeUtils.dateValueFromAbsoluteDay(n.longValue()));
return ValueDate.fromDateValue(dateValueFromAbsoluteDay(n.longValue()));
} else {
long[] a = DateTimeUtils.dateAndTimeFromValue(l);
long absoluteDay = DateTimeUtils.absoluteDayFromDateValue(a[0]);
long[] a = dateAndTimeFromValue(l);
long absoluteDay = absoluteDayFromDateValue(a[0]);
long timeNanos = a[1];
BigInteger[] dr = a2.divideAndRemainder(NANOS_PER_DAY_BI);
if (opType == IntervalOpType.DATETIME_PLUS_INTERVAL) {
......@@ -231,15 +234,14 @@ public class IntervalOperation extends Expression {
absoluteDay -= dr[0].longValue();
timeNanos -= dr[1].longValue();
}
if (timeNanos >= DateTimeUtils.NANOS_PER_DAY) {
timeNanos -= DateTimeUtils.NANOS_PER_DAY;
if (timeNanos >= NANOS_PER_DAY) {
timeNanos -= NANOS_PER_DAY;
absoluteDay++;
} else if (timeNanos < 0) {
timeNanos += DateTimeUtils.NANOS_PER_DAY;
timeNanos += NANOS_PER_DAY;
absoluteDay--;
}
return DateTimeUtils.dateTimeToValue(l, DateTimeUtils.dateValueFromAbsoluteDay(absoluteDay),
timeNanos, false);
return dateTimeToValue(l, dateValueFromAbsoluteDay(absoluteDay), timeNanos, false);
}
}
}
......
......@@ -174,7 +174,7 @@ public class TestLob extends TestDb {
return;
}
deleteDb("lob");
final String url = getURL("lob;lob_timeout=50", true);
final String url = getURL("lob;lob_timeout=200", true);
Connection conn = getConnection(url);
Statement stat = conn.createStatement();
stat.execute("create table test(id int primary key, data clob)");
......@@ -196,7 +196,7 @@ public class TestLob extends TestDb {
stat.execute("delete from test");
c1.getSubString(1, 3);
// wait until it times out
Thread.sleep(100);
Thread.sleep(250);
// start a new transaction, to be sure
stat.execute("delete from test");
assertThrows(SQLException.class, c1).getSubString(1, 3);
......
......@@ -775,3 +775,12 @@ DROP TABLE TEST;
CREATE TABLE TEST(I INTERVAL HOUR TO SECOND(10));
> exception INVALID_VALUE_SCALE_PRECISION
SELECT TIMESTAMP '2018-09-10 23:30:00' - TIMESTAMP '2014-09-11 23:30:00';
>> INTERVAL '1460 00:00:00' DAY TO SECOND
SELECT TIMESTAMP WITH TIME ZONE '2014-09-11 23:30:00Z' - TIMESTAMP WITH TIME ZONE '2018-09-10 23:30:00Z';
>> INTERVAL '-1460 00:00:00' DAY TO SECOND
SELECT DATE '2018-09-10' - DATE '2014-09-11';
>> INTERVAL '1460' DAY
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论