1 5 package org.h2.expression; 6 7 import java.sql.SQLException ; 8 9 import org.h2.engine.Constants; 10 import org.h2.engine.Database; 11 import org.h2.engine.Session; 12 import org.h2.index.IndexCondition; 13 import org.h2.message.Message; 14 import org.h2.table.ColumnResolver; 15 import org.h2.table.TableFilter; 16 import org.h2.value.Value; 17 import org.h2.value.ValueBoolean; 18 import org.h2.value.ValueNull; 19 20 23 public class Comparison extends Condition { 24 public static final int EQUAL = 0, BIGGER_EQUAL = 1, BIGGER = 2, SMALLER_EQUAL = 3, 25 SMALLER = 4, NOT_EQUAL = 5, IS_NULL = 6, IS_NOT_NULL = 7; 26 public static final int FALSE = 8; 28 private Expression left; 29 private Expression right; 30 private int compareType; 31 private int dataType = -1; 32 private Database database; 33 34 public Comparison(Session session, int compareType, Expression left, Expression right) { 35 this.database = session.getDatabase(); 36 this.left = left; 37 this.right = right; 38 this.compareType = compareType; 39 } 40 41 public String getSQL() { 42 String sql; 43 switch(compareType) { 44 case EQUAL: 45 sql = left.getSQL() + " = " + right.getSQL(); 46 break; 47 case BIGGER_EQUAL: 48 sql = left.getSQL() + " >= " + right.getSQL(); 49 break; 50 case BIGGER: 51 sql = left.getSQL() + " > " + right.getSQL(); 52 break; 53 case SMALLER_EQUAL: 54 sql = left.getSQL() + " <= " + right.getSQL(); 55 break; 56 case SMALLER: 57 sql = left.getSQL() + " < " + right.getSQL(); 58 break; 59 case NOT_EQUAL: 60 sql = left.getSQL() + " <> " + right.getSQL(); 61 break; 62 case IS_NULL: 63 sql = left.getSQL() +" IS NULL"; 64 break; 65 case IS_NOT_NULL: 66 sql = left.getSQL() +" IS NOT NULL"; 67 break; 68 default: 69 throw Message.getInternalError("compareType="+compareType); 70 } 71 return "("+sql+")"; 72 } 73 74 private Expression getCast(Expression expr, int dataType, long precision, int scale, Session session) throws SQLException { 75 if(expr == ValueExpression.NULL) { 76 return expr; 77 } 78 Function function = Function.getFunction(session.getDatabase(), "CAST"); 79 function.setParameter(0, expr); 80 function.setDataType(dataType, precision, scale); 81 return function.optimize(session); 82 } 83 84 public Expression optimize(Session session) throws SQLException { 85 left = left.optimize(session); 86 if(right == null) { 87 dataType = left.getType(); 88 } else { 89 right = right.optimize(session); 90 int lt = left.getType(), rt = right.getType(); 91 if(lt == rt) { 92 if(lt == Value.UNKNOWN) { 93 throw Message.getSQLException(Message.UNKNOWN_DATA_TYPE_1, getSQL()); 94 } 95 dataType = lt; 96 } else { 97 dataType = Value.getHigherOrder(left.getType(), right.getType()); 98 long precision = Math.max(left.getPrecision(), right.getPrecision()); 99 int scale = Math.max(left.getScale(), right.getScale()); 100 if(dataType != lt) { 101 left = getCast(left, dataType, precision, scale, session); 102 } 103 if(dataType != rt) { 104 right = getCast(right, dataType, precision, scale, session); 105 } 106 } 107 } 108 if(compareType == IS_NULL || compareType == IS_NOT_NULL) { 109 if(left.isConstant()) { 110 return ValueExpression.get(getValue(session)); 111 } 112 } else { 113 if(Constants.CHECK && (left==null || right==null)) { 114 throw Message.getInternalError(); 115 } 116 if(left == ValueExpression.NULL || right == ValueExpression.NULL) { 117 return ValueExpression.NULL; 119 } 120 if(left.isConstant() && right.isConstant()) { 121 return ValueExpression.get(getValue(session)); 122 } 123 } 124 return this; 125 } 126 127 public Value getValue(Session session) throws SQLException { 128 Value l = left.getValue(session); 129 if(right==null) { 130 boolean result; 131 switch(compareType) { 132 case IS_NULL: 133 result = l == ValueNull.INSTANCE; 134 break; 135 case IS_NOT_NULL: 136 result = !(l == ValueNull.INSTANCE); 137 break; 138 default: 139 throw Message.getInternalError("type="+compareType); 140 } 141 return ValueBoolean.get(result); 142 } 143 l = l.convertTo(dataType); 144 Value r = right.getValue(session).convertTo(dataType); 145 if(l == ValueNull.INSTANCE || r == ValueNull.INSTANCE) { 146 return ValueNull.INSTANCE; 147 } 148 boolean result = compareNotNull(database, l, r, compareType); 149 return ValueBoolean.get(result); 150 } 151 152 public static boolean compareNotNull(Database database, Value l, Value r, int compareType) throws SQLException { 153 boolean result; 154 switch(compareType) { 155 case EQUAL: 156 result = database.areEqual(l, r); 157 break; 158 case NOT_EQUAL: 159 result = !database.areEqual(l, r); 160 break; 161 case BIGGER_EQUAL: 162 result = database.compare(l, r) >= 0; 163 break; 164 case BIGGER: 165 result = database.compare(l, r) > 0; 166 break; 167 case SMALLER_EQUAL: 168 result = database.compare(l, r) <= 0; 169 break; 170 case SMALLER: 171 result = database.compare(l, r) < 0; 172 break; 173 default: 174 throw Message.getInternalError("type="+compareType); 175 } 176 return result; 177 } 178 179 private int getReversedCompareType(int type) { 180 switch(compareType) { 181 case EQUAL: 182 case NOT_EQUAL: 183 return type; 184 case BIGGER_EQUAL: 185 return SMALLER_EQUAL; 186 case BIGGER: 187 return SMALLER; 188 case SMALLER_EQUAL: 189 return BIGGER_EQUAL; 190 case SMALLER: 191 return BIGGER; 192 default: 193 throw Message.getInternalError("type="+compareType); 194 } 195 } 196 197 public void createIndexConditions(TableFilter filter) { 198 if(right==null) { 199 return; 201 } 202 ExpressionColumn l = null; 203 if(left instanceof ExpressionColumn) { 204 l = (ExpressionColumn)left; 205 if(filter != l.getTableFilter()) { 206 l = null; 207 } 208 } 209 ExpressionColumn r = null; 210 if(right instanceof ExpressionColumn) { 211 r = (ExpressionColumn)right; 212 if(filter != r.getTableFilter()) { 213 r = null; 214 } 215 } 216 if(l==null && r==null) { 218 return; 219 } 220 if(l!=null && r!=null) { 223 return; 224 } 225 boolean addIndex; 226 switch(compareType) { 227 case NOT_EQUAL: 228 addIndex = false; 229 break; 230 case EQUAL: 231 case BIGGER: 232 case BIGGER_EQUAL: 233 case SMALLER_EQUAL: 234 case SMALLER: 235 addIndex = true; 236 break; 237 default: 238 throw Message.getInternalError("type="+compareType); 239 } 240 if(addIndex) { 241 if(l!=null) { 242 filter.addIndexCondition(new IndexCondition(compareType, l, right)); 243 } else if(r!=null) { 244 int compareRev = getReversedCompareType(compareType); 245 filter.addIndexCondition(new IndexCondition(compareRev, r, left)); 246 } 247 } 248 } 249 250 public void setEvaluatable(TableFilter tableFilter, boolean b) { 251 left.setEvaluatable(tableFilter, b); 252 if(right != null) { 253 right.setEvaluatable(tableFilter, b); 254 } 255 } 256 257 public void updateAggregate(Session session) throws SQLException { 258 left.updateAggregate(session); 259 if(right != null) { 260 right.updateAggregate(session); 261 } 262 } 263 264 public void addFilterConditions(TableFilter filter, boolean outerJoin) { 265 if(compareType == IS_NULL && outerJoin) { 266 return; 271 } 272 super.addFilterConditions(filter, outerJoin); 273 } 274 275 public void mapColumns(ColumnResolver resolver, int level) throws SQLException { 276 left.mapColumns(resolver, level); 277 if(right!=null) { 278 right.mapColumns(resolver, level); 279 } 280 } 281 282 public boolean isEverything(ExpressionVisitor visitor) { 283 return left.isEverything(visitor) && (right == null || right.isEverything(visitor)); 284 } 285 286 public int getCost() { 287 return left.getCost() + (right == null ? 0 : right.getCost()) + 1; 288 } 289 290 } 291 | Popular Tags |