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 ...@@ -21,6 +21,24 @@ Change Log
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul> <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>PR #1454: Add FIRST_VALUE(), LAST_VALUE(), and NTH_VALUE()
</li> </li>
<li>PR #1453, Issue #1161: Add ROW_NUMBER(), RANK(), DENSE_RANK(), PERCENT_RANK(), and CUME_DIST() window functions <li>PR #1453, Issue #1161: Add ROW_NUMBER(), RANK(), DENSE_RANK(), PERCENT_RANK(), and CUME_DIST() window functions
......
...@@ -5,6 +5,11 @@ ...@@ -5,6 +5,11 @@
*/ */
package org.h2.expression; 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 static org.h2.util.IntervalUtils.NANOS_PER_DAY_BI;
import java.math.BigDecimal; import java.math.BigDecimal;
...@@ -17,7 +22,6 @@ import org.h2.message.DbException; ...@@ -17,7 +22,6 @@ import org.h2.message.DbException;
import org.h2.table.ColumnResolver; import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter; import org.h2.table.TableFilter;
import org.h2.util.DateTimeFunctions; import org.h2.util.DateTimeFunctions;
import org.h2.util.DateTimeUtils;
import org.h2.util.IntervalUtils; import org.h2.util.IntervalUtils;
import org.h2.value.DataType; import org.h2.value.DataType;
import org.h2.value.Value; import org.h2.value.Value;
...@@ -73,6 +77,12 @@ public class IntervalOperation extends Expression { ...@@ -73,6 +77,12 @@ public class IntervalOperation extends Expression {
private Expression left, right; private Expression left, right;
private int dataType; 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) { public IntervalOperation(IntervalOpType opType, Expression left, Expression right) {
this.opType = opType; this.opType = opType;
this.left = left; this.left = left;
...@@ -161,21 +171,15 @@ public class IntervalOperation extends Expression { ...@@ -161,21 +171,15 @@ public class IntervalOperation extends Expression {
return ValueInterval.from(IntervalQualifier.HOUR_TO_SECOND, negative, diff / 3_600_000_000_000L, return ValueInterval.from(IntervalQualifier.HOUR_TO_SECOND, negative, diff / 3_600_000_000_000L,
diff % 3_600_000_000_000L); diff % 3_600_000_000_000L);
} else if (lType == Value.DATE && rType == Value.DATE) { } else if (lType == Value.DATE && rType == Value.DATE) {
long diff = DateTimeUtils.absoluteDayFromDateValue(((ValueDate) l).getDateValue()) long diff = absoluteDayFromDateValue(((ValueDate) l).getDateValue())
- DateTimeUtils.absoluteDayFromDateValue(((ValueDate) r).getDateValue()); - absoluteDayFromDateValue(((ValueDate) r).getDateValue());
boolean negative = diff < 0; boolean negative = diff < 0;
if (negative) { if (negative) {
diff = -diff; diff = -diff;
} }
return ValueInterval.from(IntervalQualifier.DAY, negative, diff, 0L); return ValueInterval.from(IntervalQualifier.DAY, negative, diff, 0L);
} else { } else {
long[] a = DateTimeUtils.dateAndTimeFromValue(l); BigInteger diff = nanosFromValue(l).subtract(nanosFromValue(r));
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);
if (lType == Value.TIMESTAMP_TZ || rType == Value.TIMESTAMP_TZ) { if (lType == Value.TIMESTAMP_TZ || rType == Value.TIMESTAMP_TZ) {
l = l.convertTo(Value.TIMESTAMP_TZ); l = l.convertTo(Value.TIMESTAMP_TZ);
r = r.convertTo(Value.TIMESTAMP_TZ); r = r.convertTo(Value.TIMESTAMP_TZ);
...@@ -214,14 +218,13 @@ public class IntervalOperation extends Expression { ...@@ -214,14 +218,13 @@ public class IntervalOperation extends Expression {
} else { } else {
BigInteger a2 = IntervalUtils.intervalToAbsolute((ValueInterval) r); BigInteger a2 = IntervalUtils.intervalToAbsolute((ValueInterval) r);
if (lType == Value.DATE) { if (lType == Value.DATE) {
BigInteger a1 = BigInteger BigInteger a1 = BigInteger.valueOf(absoluteDayFromDateValue(((ValueDate) l).getDateValue()));
.valueOf(DateTimeUtils.absoluteDayFromDateValue(((ValueDate) l).getDateValue()));
a2 = a2.divide(NANOS_PER_DAY_BI); a2 = a2.divide(NANOS_PER_DAY_BI);
BigInteger n = opType == IntervalOpType.DATETIME_PLUS_INTERVAL ? a1.add(a2) : a1.subtract(a2); 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 { } else {
long[] a = DateTimeUtils.dateAndTimeFromValue(l); long[] a = dateAndTimeFromValue(l);
long absoluteDay = DateTimeUtils.absoluteDayFromDateValue(a[0]); long absoluteDay = absoluteDayFromDateValue(a[0]);
long timeNanos = a[1]; long timeNanos = a[1];
BigInteger[] dr = a2.divideAndRemainder(NANOS_PER_DAY_BI); BigInteger[] dr = a2.divideAndRemainder(NANOS_PER_DAY_BI);
if (opType == IntervalOpType.DATETIME_PLUS_INTERVAL) { if (opType == IntervalOpType.DATETIME_PLUS_INTERVAL) {
...@@ -231,15 +234,14 @@ public class IntervalOperation extends Expression { ...@@ -231,15 +234,14 @@ public class IntervalOperation extends Expression {
absoluteDay -= dr[0].longValue(); absoluteDay -= dr[0].longValue();
timeNanos -= dr[1].longValue(); timeNanos -= dr[1].longValue();
} }
if (timeNanos >= DateTimeUtils.NANOS_PER_DAY) { if (timeNanos >= NANOS_PER_DAY) {
timeNanos -= DateTimeUtils.NANOS_PER_DAY; timeNanos -= NANOS_PER_DAY;
absoluteDay++; absoluteDay++;
} else if (timeNanos < 0) { } else if (timeNanos < 0) {
timeNanos += DateTimeUtils.NANOS_PER_DAY; timeNanos += NANOS_PER_DAY;
absoluteDay--; absoluteDay--;
} }
return DateTimeUtils.dateTimeToValue(l, DateTimeUtils.dateValueFromAbsoluteDay(absoluteDay), return dateTimeToValue(l, dateValueFromAbsoluteDay(absoluteDay), timeNanos, false);
timeNanos, false);
} }
} }
} }
......
...@@ -174,7 +174,7 @@ public class TestLob extends TestDb { ...@@ -174,7 +174,7 @@ public class TestLob extends TestDb {
return; return;
} }
deleteDb("lob"); deleteDb("lob");
final String url = getURL("lob;lob_timeout=50", true); final String url = getURL("lob;lob_timeout=200", true);
Connection conn = getConnection(url); Connection conn = getConnection(url);
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
stat.execute("create table test(id int primary key, data clob)"); stat.execute("create table test(id int primary key, data clob)");
...@@ -196,7 +196,7 @@ public class TestLob extends TestDb { ...@@ -196,7 +196,7 @@ public class TestLob extends TestDb {
stat.execute("delete from test"); stat.execute("delete from test");
c1.getSubString(1, 3); c1.getSubString(1, 3);
// wait until it times out // wait until it times out
Thread.sleep(100); Thread.sleep(250);
// start a new transaction, to be sure // start a new transaction, to be sure
stat.execute("delete from test"); stat.execute("delete from test");
assertThrows(SQLException.class, c1).getSubString(1, 3); assertThrows(SQLException.class, c1).getSubString(1, 3);
......
...@@ -775,3 +775,12 @@ DROP TABLE TEST; ...@@ -775,3 +775,12 @@ DROP TABLE TEST;
CREATE TABLE TEST(I INTERVAL HOUR TO SECOND(10)); CREATE TABLE TEST(I INTERVAL HOUR TO SECOND(10));
> exception INVALID_VALUE_SCALE_PRECISION > 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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论