提交 4c241336 authored 作者: Thomas Mueller's avatar Thomas Mueller

Improved date / time arithmetics.

上级 1114d838
...@@ -55,6 +55,7 @@ public class Operation extends Expression { ...@@ -55,6 +55,7 @@ public class Operation extends Expression {
private int opType; private int opType;
private Expression left, right; private Expression left, right;
private int dataType; private int dataType;
private boolean convertRight = true;
public Operation(int opType, Expression left, Expression right) { public Operation(int opType, Expression left, Expression right) {
this.opType = opType; this.opType = opType;
...@@ -64,37 +65,48 @@ public class Operation extends Expression { ...@@ -64,37 +65,48 @@ public class Operation extends Expression {
public String getSQL() { public String getSQL() {
String sql; String sql;
switch (opType) { if (opType == NEGATE) {
case NEGATE:
// don't remove the space, otherwise it might end up some thing like // don't remove the space, otherwise it might end up some thing like
// --1 which is a line remark // --1 which is a line remark
sql = "- " + left.getSQL(); sql = "- " + left.getSQL();
break; } else {
// don't remove the space, otherwise it might end up some thing like
// --1 which is a line remark
sql = left.getSQL() + " " + getOperationToken() + " " + right.getSQL();
}
return "(" + sql + ")";
}
private String getOperationToken() {
switch (opType) {
case NEGATE:
return "-";
case CONCAT: case CONCAT:
sql = left.getSQL() + " || " + right.getSQL(); return "||";
break;
case PLUS: case PLUS:
sql = left.getSQL() + " + " + right.getSQL(); return "+";
break;
case MINUS: case MINUS:
sql = left.getSQL() + " - " + right.getSQL(); return "-";
break;
case MULTIPLY: case MULTIPLY:
sql = left.getSQL() + " * " + right.getSQL(); return "*";
break;
case DIVIDE: case DIVIDE:
sql = left.getSQL() + " / " + right.getSQL(); return "/";
break;
default: default:
throw DbException.throwInternalError("opType=" + opType); throw DbException.throwInternalError("opType=" + opType);
} }
return "(" + sql + ")";
} }
public Value getValue(Session session) { public Value getValue(Session session) {
Value l = left.getValue(session).convertTo(dataType); Value l = left.getValue(session).convertTo(dataType);
Value r = right == null ? null : right.getValue(session).convertTo(dataType); Value r;
if (right == null) {
r = null;
} else {
r = right.getValue(session);
if (convertRight) {
r = r.convertTo(dataType);
}
}
switch (opType) { switch (opType) {
case NEGATE: case NEGATE:
return l == ValueNull.INSTANCE ? l : l.negate(); return l == ValueNull.INSTANCE ? l : l.negate();
...@@ -180,28 +192,81 @@ public class Operation extends Expression { ...@@ -180,28 +192,81 @@ public class Operation extends Expression {
} else { } else {
dataType = Value.DECIMAL; dataType = Value.DECIMAL;
} }
} else if (l == Value.DATE || l == Value.TIMESTAMP) { } else if (l == Value.DATE || l == Value.TIMESTAMP || l == Value.TIME ||
if (r == Value.INT && (opType == PLUS || opType == MINUS)) { r == Value.DATE || r == Value.TIMESTAMP || r == Value.TIME) {
// Oracle date add if (opType == PLUS) {
Function f = Function.getFunction(session.getDatabase(), "DATEADD"); if (r != Value.getHigherOrder(l, r)) {
f.setParameter(0, ValueExpression.get(ValueString.get("DAY"))); // order left and right: INT < TIME < DATE < TIMESTAMP
if (opType == MINUS) { swap();
int t = l;
l = r;
r = t;
}
if (l == Value.INT) {
// Oracle date add
Function f = Function.getFunction(session.getDatabase(), "DATEADD");
f.setParameter(0, ValueExpression.get(ValueString.get("DAY")));
f.setParameter(1, left);
f.setParameter(2, right);
f.doneWithParameters();
return f.optimize(session);
} else if (l == Value.TIME && r == Value.TIME) {
dataType = Value.TIME;
return this;
} else if (l == Value.TIME) {
dataType = Value.TIMESTAMP;
return this;
}
} else if (opType == MINUS) {
if ((l == Value.DATE || l == Value.TIMESTAMP) && r == Value.INT) {
// Oracle date subtract
Function f = Function.getFunction(session.getDatabase(), "DATEADD");
f.setParameter(0, ValueExpression.get(ValueString.get("DAY")));
right = new Operation(NEGATE, right, null); right = new Operation(NEGATE, right, null);
right = right.optimize(session); right = right.optimize(session);
f.setParameter(1, right);
f.setParameter(2, left);
f.doneWithParameters();
return f.optimize(session);
} else if (l == Value.DATE || l == Value.TIMESTAMP) {
if (r == Value.TIME) {
dataType = Value.TIMESTAMP;
return this;
} else if (r == Value.DATE || r == Value.TIMESTAMP) {
// Oracle date subtract
Function f = Function.getFunction(session.getDatabase(), "DATEDIFF");
f.setParameter(0, ValueExpression.get(ValueString.get("DAY")));
f.setParameter(1, right);
f.setParameter(2, left);
f.doneWithParameters();
return f.optimize(session);
}
} else if (l == Value.TIME && r == Value.TIME) {
dataType = Value.TIME;
return this;
}
} else if (opType == MULTIPLY) {
if (l == Value.TIME) {
dataType = Value.TIME;
convertRight = false;
return this;
} else if (r == Value.TIME) {
swap();
dataType = Value.TIME;
convertRight = false;
return this;
}
} else if (opType == DIVIDE) {
if (l == Value.TIME) {
dataType = Value.TIME;
convertRight = false;
return this;
} }
f.setParameter(1, right);
f.setParameter(2, left);
f.doneWithParameters();
return f.optimize(session);
} else if (opType == MINUS && (l == Value.DATE || l == Value.TIMESTAMP)) {
// Oracle date subtract
Function f = Function.getFunction(session.getDatabase(), "DATEDIFF");
f.setParameter(0, ValueExpression.get(ValueString.get("DAY")));
f.setParameter(1, right);
f.setParameter(2, left);
f.doneWithParameters();
return f.optimize(session);
} }
throw DbException.getUnsupportedException(
DataType.getDataType(l).name + " " +
getOperationToken() + " " +
DataType.getDataType(r).name);
} else { } else {
dataType = Value.getHigherOrder(l, r); dataType = Value.getHigherOrder(l, r);
if (DataType.isStringType(dataType) && session.getDatabase().getMode().allowPlusForStringConcat) { if (DataType.isStringType(dataType) && session.getDatabase().getMode().allowPlusForStringConcat) {
...@@ -218,6 +283,12 @@ public class Operation extends Expression { ...@@ -218,6 +283,12 @@ public class Operation extends Expression {
return this; return this;
} }
private void swap() {
Expression temp = left;
left = right;
right = temp;
}
public void setEvaluatable(TableFilter tableFilter, boolean b) { public void setEvaluatable(TableFilter tableFilter, boolean b) {
left.setEvaluatable(tableFilter, b); left.setEvaluatable(tableFilter, b);
if (right != null) { if (right != null) {
......
...@@ -117,4 +117,28 @@ public class ValueTime extends Value { ...@@ -117,4 +117,28 @@ public class ValueTime extends Value {
return other instanceof ValueTime && value.equals(((ValueTime) other).value); return other instanceof ValueTime && value.equals(((ValueTime) other).value);
} }
public Value add(Value v) {
Time t = new Time(value.getTime() + v.getTime().getTime());
return ValueTime.get(t);
}
public Value subtract(Value v) {
Time t = new Time(value.getTime() - v.getTime().getTime());
return ValueTime.get(t);
}
public Value multiply(Value v) {
long zeroTime = ValueTime.get(new Time(0)).getDate().getTime();
long t = value.getTime() - zeroTime;
t = (long) (t * v.getDouble()) + zeroTime;
return ValueTime.get(new Time(t));
}
public Value divide(Value v) {
long zeroTime = ValueTime.get(new Time(0)).getDate().getTime();
long t = value.getTime() - zeroTime;
t = (long) (t / v.getDouble()) + zeroTime;
return ValueTime.get(new Time(t));
}
} }
...@@ -9,6 +9,7 @@ package org.h2.value; ...@@ -9,6 +9,7 @@ package org.h2.value;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.Calendar; import java.util.Calendar;
...@@ -180,4 +181,18 @@ public class ValueTimestamp extends Value { ...@@ -180,4 +181,18 @@ public class ValueTimestamp extends Value {
return other instanceof ValueTimestamp && value.equals(((ValueTimestamp) other).value); return other instanceof ValueTimestamp && value.equals(((ValueTimestamp) other).value);
} }
public Value add(Value v) {
long zeroTime = ValueTime.get(new Time(0)).getDate().getTime();
long t = value.getTime() - zeroTime + v.getTimestamp().getTime();
Timestamp ts = new Timestamp(t);
return ValueTimestamp.get(ts);
}
public Value subtract(Value v) {
long zeroTime = ValueTime.get(new Time(0)).getDate().getTime();
long t = value.getTime() + zeroTime - v.getTimestamp().getTime();
Timestamp ts = new Timestamp(t);
return ValueTimestamp.get(ts);
}
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论