1 5 package org.h2.expression; 6 7 import java.sql.SQLException ; 8 9 import org.h2.engine.Mode; 10 import org.h2.engine.Session; 11 import org.h2.message.Message; 12 import org.h2.table.ColumnResolver; 13 import org.h2.table.TableFilter; 14 import org.h2.value.Value; 15 import org.h2.value.ValueNull; 16 import org.h2.value.ValueString; 17 18 public class Operation extends Expression { 19 public static final int CONCAT = 0, PLUS = 1, MINUS = 2, MULTIPLY = 3, 20 DIVIDE = 4, NEGATE = 5; 21 private int opType; 22 private Expression left, right; 23 private int dataType; 24 25 public Operation(int opType, Expression left, Expression right) { 26 this.opType = opType; 27 this.left = left; 28 this.right = right; 29 } 30 31 public String getSQL() { 32 String sql; 33 switch(opType) { 34 case NEGATE: 35 sql = "- " + left.getSQL(); 38 break; 39 case CONCAT: 40 sql = left.getSQL() + " || " + right.getSQL(); 41 break; 42 case PLUS: 43 sql = left.getSQL() + " + " + right.getSQL(); 44 break; 45 case MINUS: 46 sql = left.getSQL() + " - " + right.getSQL(); 47 break; 48 case MULTIPLY: 49 sql = left.getSQL() + " * " + right.getSQL(); 50 break; 51 case DIVIDE: 52 sql = left.getSQL() + " / " + right.getSQL(); 53 break; 54 default: 55 throw Message.getInternalError("opType="+opType); 56 } 57 return "("+sql+")"; 58 } 59 60 public Value getValue(Session session) throws SQLException { 61 Value l = left.getValue(session).convertTo(dataType); 62 Value r = right == null ? null : right.getValue(session).convertTo(dataType); 63 64 switch (opType) { 65 case NEGATE: 66 return l == ValueNull.INSTANCE ? l : l.negate(); 67 case CONCAT: { 68 if (l == ValueNull.INSTANCE) { 69 if(Mode.getCurrentMode().nullConcatIsNull) { 70 return ValueNull.INSTANCE; 71 } else { 72 return r; 73 } 74 } else if (r == ValueNull.INSTANCE) { 75 if(Mode.getCurrentMode().nullConcatIsNull) { 76 return ValueNull.INSTANCE; 77 } else { 78 return l; 79 } 80 } 81 String s1 = l.getString(), s2 = r.getString(); 82 StringBuffer buff = new StringBuffer (s1.length() + s2.length()); 83 buff.append(s1); 84 buff.append(s2); 85 return ValueString.get(buff.toString()); 86 } 87 case PLUS: 88 if(l == ValueNull.INSTANCE || r == ValueNull.INSTANCE) { 89 return ValueNull.INSTANCE; 90 } 91 return l.add(r); 92 case MINUS: 93 if(l == ValueNull.INSTANCE || r == ValueNull.INSTANCE) { 94 return ValueNull.INSTANCE; 95 } 96 return l.subtract(r); 97 case MULTIPLY: 98 if(l == ValueNull.INSTANCE || r == ValueNull.INSTANCE) { 99 return ValueNull.INSTANCE; 100 } 101 return l.multiply(r); 102 case DIVIDE: 103 if(l == ValueNull.INSTANCE || r == ValueNull.INSTANCE) { 104 return ValueNull.INSTANCE; 105 } 106 return l.divide(r); 107 default: 108 throw Message.getInternalError("type=" + opType); 109 } 110 } 111 112 public void mapColumns(ColumnResolver resolver, int level) throws SQLException { 113 left.mapColumns(resolver, level); 114 if(right != null) { 115 right.mapColumns(resolver, level); 116 } 117 } 118 119 public Expression optimize(Session session) throws SQLException { 120 left = left.optimize(session); 121 switch (opType) { 122 case NEGATE: 123 dataType = left.getType(); 124 break; 125 case CONCAT: 126 right = right.optimize(session); 127 dataType = Value.STRING; 128 if(left.isConstant() && right.isConstant()) { 129 return ValueExpression.get(getValue(session)); 130 } 131 break; 132 case PLUS: 133 case MINUS: 134 case MULTIPLY: 135 case DIVIDE: 136 right = right.optimize(session); 137 int l = left.getType(); 138 int r = right.getType(); 139 if(l==Value.NULL && r==Value.NULL) { 140 dataType = Value.DECIMAL; 142 } else if(l == Value.DATE || l == Value.TIMESTAMP) { 143 if(r == Value.INT && (opType == PLUS || opType == MINUS)) { 144 Function f = Function.getFunction(session.getDatabase(), "DATEADD"); 146 f.setParameter(0, ValueExpression.get(ValueString.get("DAY"))); 147 if(opType == MINUS) { 148 right = new Operation(NEGATE, right, null); 149 right = right.optimize(session); 150 } 151 f.setParameter(1, right); 152 f.setParameter(2, left); 153 f.doneWithParameters(); 154 return f.optimize(session); 155 } else if(opType == MINUS && (l == Value.DATE || l == Value.TIMESTAMP)) { 156 Function f = Function.getFunction(session.getDatabase(), "DATEDIFF"); 158 f.setParameter(0, ValueExpression.get(ValueString.get("DAY"))); 159 f.setParameter(1, right); 160 f.setParameter(2, left); 161 f.doneWithParameters(); 162 return f.optimize(session); 163 } 164 } else { 165 dataType = Value.getHigherOrder(l, r); 166 } 167 break; 168 default: 169 throw Message.getInternalError("type=" + opType); 170 } 171 if(left.isConstant() && (right==null || right.isConstant())) { 172 return ValueExpression.get(getValue(session)); 173 } 174 return this; 175 } 176 177 public void setEvaluatable(TableFilter tableFilter, boolean b) { 178 left.setEvaluatable(tableFilter, b); 179 if(right != null) { 180 right.setEvaluatable(tableFilter, b); 181 } 182 } 183 184 public int getType() { 185 return dataType; 186 } 187 188 public long getPrecision() { 189 if(right != null) { 190 return Math.max(left.getPrecision(), right.getPrecision()); 191 } 192 return left.getPrecision(); 193 } 194 195 public int getScale() { 196 if(right != null) { 197 return Math.max(left.getScale(), right.getScale()); 198 } 199 return left.getScale(); 200 } 201 202 public void updateAggregate(Session session) throws SQLException { 203 left.updateAggregate(session); 204 if(right != null) { 205 right.updateAggregate(session); 206 } 207 } 208 209 public boolean isEverything(ExpressionVisitor visitor) { 210 return left.isEverything(visitor) && (right == null || right.isEverything(visitor)); 211 } 212 213 public int getCost() { 214 return left.getCost() + 1 + (right == null ? 0 : right.getCost()); 215 } 216 217 } 218 | Popular Tags |