提交 46f038af authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Extract UnaryOperation from Operation to simplify logic

上级 04b85386
...@@ -170,6 +170,7 @@ import org.h2.expression.Rownum; ...@@ -170,6 +170,7 @@ import org.h2.expression.Rownum;
import org.h2.expression.SequenceValue; import org.h2.expression.SequenceValue;
import org.h2.expression.Subquery; import org.h2.expression.Subquery;
import org.h2.expression.TableFunction; import org.h2.expression.TableFunction;
import org.h2.expression.UnaryOperation;
import org.h2.expression.ValueExpression; import org.h2.expression.ValueExpression;
import org.h2.expression.Variable; import org.h2.expression.Variable;
import org.h2.expression.Wildcard; import org.h2.expression.Wildcard;
...@@ -3551,7 +3552,7 @@ public class Parser { ...@@ -3551,7 +3552,7 @@ public class Parser {
} }
read(); read();
} else { } else {
r = new Operation(OpType.NEGATE, readTerm(), null); r = new UnaryOperation(readTerm());
} }
break; break;
case PLUS_SIGN: case PLUS_SIGN:
......
...@@ -24,6 +24,7 @@ import org.h2.expression.ExpressionVisitor; ...@@ -24,6 +24,7 @@ import org.h2.expression.ExpressionVisitor;
import org.h2.expression.Function; import org.h2.expression.Function;
import org.h2.expression.Operation; import org.h2.expression.Operation;
import org.h2.expression.Parameter; import org.h2.expression.Parameter;
import org.h2.expression.UnaryOperation;
import org.h2.expression.ValueExpression; import org.h2.expression.ValueExpression;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.result.ResultInterface; import org.h2.result.ResultInterface;
...@@ -555,6 +556,9 @@ public abstract class Query extends Prepared { ...@@ -555,6 +556,9 @@ public abstract class Query extends Prepared {
return checkOrderOther(session, operation.getLeftSubExpression(), expressionSQL) return checkOrderOther(session, operation.getLeftSubExpression(), expressionSQL)
&& (right == null || checkOrderOther(session, right, expressionSQL)); && (right == null || checkOrderOther(session, right, expressionSQL));
} }
if (expr instanceof UnaryOperation) {
return checkOrderOther(session, ((UnaryOperation) expr).getSubExpression(), expressionSQL);
}
if (expr instanceof ConditionAndOr) { if (expr instanceof ConditionAndOr) {
ConditionAndOr condition = (ConditionAndOr) expr; ConditionAndOr condition = (ConditionAndOr) expr;
return checkOrderOther(session, condition.getLeftSubExpression(), expressionSQL) return checkOrderOther(session, condition.getLeftSubExpression(), expressionSQL)
......
...@@ -50,11 +50,6 @@ public class Operation extends Expression { ...@@ -50,11 +50,6 @@ public class Operation extends Expression {
*/ */
DIVIDE, DIVIDE,
/**
* This operation represents a negation as in - ID.
*/
NEGATE,
/** /**
* This operation represents a modulus as in 5 % 2. * This operation represents a modulus as in 5 % 2.
*/ */
...@@ -74,23 +69,13 @@ public class Operation extends Expression { ...@@ -74,23 +69,13 @@ public class Operation extends Expression {
@Override @Override
public String getSQL() { public String getSQL() {
String sql;
if (opType == OpType.NEGATE) {
// don't remove the space, otherwise it might end up some thing like
// --1 which is a line remark
sql = "- " + left.getSQL();
} else {
// 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() + " " + getOperationToken() + " " + right.getSQL(); return '(' + left.getSQL() + ' ' + getOperationToken() + ' ' + right.getSQL() + ')';
}
return "(" + sql + ")";
} }
private String getOperationToken() { private String getOperationToken() {
switch (opType) { switch (opType) {
case NEGATE:
return "-";
case CONCAT: case CONCAT:
return "||"; return "||";
case PLUS: case PLUS:
...@@ -112,18 +97,11 @@ public class Operation extends Expression { ...@@ -112,18 +97,11 @@ public class Operation extends Expression {
public Value getValue(Session session) { public Value getValue(Session session) {
Mode mode = session.getDatabase().getMode(); Mode mode = session.getDatabase().getMode();
Value l = left.getValue(session).convertTo(dataType, mode); Value l = left.getValue(session).convertTo(dataType, mode);
Value r; Value r = right.getValue(session);
if (right == null) {
r = null;
} else {
r = right.getValue(session);
if (convertRight) { if (convertRight) {
r = r.convertTo(dataType, mode); r = r.convertTo(dataType, mode);
} }
}
switch (opType) { switch (opType) {
case NEGATE:
return l == ValueNull.INSTANCE ? l : l.negate();
case CONCAT: { case CONCAT: {
if (l == ValueNull.INSTANCE) { if (l == ValueNull.INSTANCE) {
if (mode.nullConcatIsNull) { if (mode.nullConcatIsNull) {
...@@ -174,25 +152,15 @@ public class Operation extends Expression { ...@@ -174,25 +152,15 @@ public class Operation extends Expression {
@Override @Override
public void mapColumns(ColumnResolver resolver, int level) { public void mapColumns(ColumnResolver resolver, int level) {
left.mapColumns(resolver, level); left.mapColumns(resolver, level);
if (right != null) {
right.mapColumns(resolver, level); right.mapColumns(resolver, level);
} }
}
@Override @Override
public Expression optimize(Session session) { public Expression optimize(Session session) {
left = left.optimize(session); left = left.optimize(session);
right = right.optimize(session);
switch (opType) { switch (opType) {
case NEGATE:
dataType = left.getType();
if (dataType == Value.UNKNOWN) {
dataType = Value.DECIMAL;
} else if (dataType == Value.ENUM) {
dataType = Value.INT;
}
break;
case CONCAT: case CONCAT:
right = right.optimize(session);
dataType = Value.STRING; dataType = Value.STRING;
if (left.isConstant() && right.isConstant()) { if (left.isConstant() && right.isConstant()) {
return ValueExpression.get(getValue(session)); return ValueExpression.get(getValue(session));
...@@ -203,7 +171,6 @@ public class Operation extends Expression { ...@@ -203,7 +171,6 @@ public class Operation extends Expression {
case MULTIPLY: case MULTIPLY:
case DIVIDE: case DIVIDE:
case MODULUS: case MODULUS:
right = right.optimize(session);
int l = left.getType(); int l = left.getType();
int r = right.getType(); int r = right.getType();
if ((l == Value.NULL && r == Value.NULL) || if ((l == Value.NULL && r == Value.NULL) ||
...@@ -234,7 +201,7 @@ public class Operation extends Expression { ...@@ -234,7 +201,7 @@ public class Operation extends Expression {
default: default:
DbException.throwInternalError("type=" + opType); DbException.throwInternalError("type=" + opType);
} }
if (left.isConstant() && (right == null || right.isConstant())) { if (left.isConstant() && right.isConstant()) {
return ValueExpression.get(getValue(session)); return ValueExpression.get(getValue(session));
} }
return this; return this;
...@@ -361,7 +328,7 @@ public class Operation extends Expression { ...@@ -361,7 +328,7 @@ public class Operation extends Expression {
// Oracle date subtract // Oracle date subtract
Function f = Function.getFunction(session.getDatabase(), "DATEADD"); Function f = Function.getFunction(session.getDatabase(), "DATEADD");
f.setParameter(0, ValueExpression.get(ValueString.get("DAY"))); f.setParameter(0, ValueExpression.get(ValueString.get("DAY")));
right = new Operation(OpType.NEGATE, right, null); right = new UnaryOperation(right);
right = right.optimize(session); right = right.optimize(session);
f.setParameter(1, right); f.setParameter(1, right);
f.setParameter(2, left); f.setParameter(2, left);
...@@ -376,7 +343,7 @@ public class Operation extends Expression { ...@@ -376,7 +343,7 @@ public class Operation extends Expression {
f.setParameter(0, ValueExpression.get(ValueString.get("SECOND"))); f.setParameter(0, ValueExpression.get(ValueString.get("SECOND")));
right = new Operation(OpType.MULTIPLY, ValueExpression.get(ValueInt right = new Operation(OpType.MULTIPLY, ValueExpression.get(ValueInt
.get(60 * 60 * 24)), right); .get(60 * 60 * 24)), right);
right = new Operation(OpType.NEGATE, right, null); right = new UnaryOperation(right);
right = right.optimize(session); right = right.optimize(session);
f.setParameter(1, right); f.setParameter(1, right);
f.setParameter(2, left); f.setParameter(2, left);
...@@ -437,10 +404,8 @@ public class Operation extends Expression { ...@@ -437,10 +404,8 @@ public class Operation extends Expression {
@Override @Override
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) {
right.setEvaluatable(tableFilter, b); right.setEvaluatable(tableFilter, b);
} }
}
@Override @Override
public int getType() { public int getType() {
...@@ -449,7 +414,6 @@ public class Operation extends Expression { ...@@ -449,7 +414,6 @@ public class Operation extends Expression {
@Override @Override
public long getPrecision() { public long getPrecision() {
if (right != null) {
switch (opType) { switch (opType) {
case CONCAT: case CONCAT:
return left.getPrecision() + right.getPrecision(); return left.getPrecision() + right.getPrecision();
...@@ -457,12 +421,9 @@ public class Operation extends Expression { ...@@ -457,12 +421,9 @@ public class Operation extends Expression {
return Math.max(left.getPrecision(), right.getPrecision()); return Math.max(left.getPrecision(), right.getPrecision());
} }
} }
return left.getPrecision();
}
@Override @Override
public int getDisplaySize() { public int getDisplaySize() {
if (right != null) {
switch (opType) { switch (opType) {
case CONCAT: case CONCAT:
return MathUtils.convertLongToInt((long) left.getDisplaySize() + return MathUtils.convertLongToInt((long) left.getDisplaySize() +
...@@ -471,34 +432,26 @@ public class Operation extends Expression { ...@@ -471,34 +432,26 @@ public class Operation extends Expression {
return Math.max(left.getDisplaySize(), right.getDisplaySize()); return Math.max(left.getDisplaySize(), right.getDisplaySize());
} }
} }
return left.getDisplaySize();
}
@Override @Override
public int getScale() { public int getScale() {
if (right != null) {
return Math.max(left.getScale(), right.getScale()); return Math.max(left.getScale(), right.getScale());
} }
return left.getScale();
}
@Override @Override
public void updateAggregate(Session session) { public void updateAggregate(Session session) {
left.updateAggregate(session); left.updateAggregate(session);
if (right != null) {
right.updateAggregate(session); right.updateAggregate(session);
} }
}
@Override @Override
public boolean isEverything(ExpressionVisitor visitor) { public boolean isEverything(ExpressionVisitor visitor) {
return left.isEverything(visitor) && return left.isEverything(visitor) && right.isEverything(visitor);
(right == null || right.isEverything(visitor));
} }
@Override @Override
public int getCost() { public int getCost() {
return left.getCost() + 1 + (right == null ? 0 : right.getCost()); return left.getCost() + right.getCost() + 1;
} }
/** /**
......
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.expression;
import org.h2.engine.Session;
import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.value.Value;
import org.h2.value.ValueNull;
/**
* Unary operation. Only negation operation is currently supported.
*/
public class UnaryOperation extends Expression {
private Expression arg;
private int dataType;
public UnaryOperation(Expression arg) {
this.arg = arg;
}
@Override
public String getSQL() {
// don't remove the space, otherwise it might end up some thing like
// --1 which is a line remark
return "(- " + arg.getSQL() + ')';
}
@Override
public Value getValue(Session session) {
Value a = arg.getValue(session).convertTo(dataType, session.getDatabase().getMode());
return a == ValueNull.INSTANCE ? a : a.negate();
}
@Override
public void mapColumns(ColumnResolver resolver, int level) {
arg.mapColumns(resolver, level);
}
@Override
public Expression optimize(Session session) {
arg = arg.optimize(session);
dataType = arg.getType();
if (dataType == Value.UNKNOWN) {
dataType = Value.DECIMAL;
} else if (dataType == Value.ENUM) {
dataType = Value.INT;
}
if (arg.isConstant()) {
return ValueExpression.get(getValue(session));
}
return this;
}
@Override
public void setEvaluatable(TableFilter tableFilter, boolean b) {
arg.setEvaluatable(tableFilter, b);
}
@Override
public int getType() {
return dataType;
}
@Override
public long getPrecision() {
return arg.getPrecision();
}
@Override
public int getDisplaySize() {
return arg.getDisplaySize();
}
@Override
public int getScale() {
return arg.getScale();
}
@Override
public void updateAggregate(Session session) {
arg.updateAggregate(session);
}
@Override
public boolean isEverything(ExpressionVisitor visitor) {
return arg.isEverything(visitor);
}
@Override
public int getCost() {
return arg.getCost() + 1;
}
/**
* Get the sub-expression of this operation.
*
* @return the sub-expression
*/
public Expression getSubExpression() {
return arg;
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论