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.table.ColumnResolver; 14 import org.h2.table.TableFilter; 15 import org.h2.util.ObjectArray; 16 import org.h2.value.CompareMode; 17 import org.h2.value.Value; 18 import org.h2.value.ValueBoolean; 19 import org.h2.value.ValueNull; 20 21 24 25 public class ConditionIn extends Condition { 26 private Database database; 27 private Expression left; 28 private ObjectArray values; 29 private Value min, max; 30 private int queryLevel; 31 32 public ConditionIn(Database database, Expression left, ObjectArray values) { 33 this.database = database; 34 this.left = left; 35 this.values = values; 36 } 37 38 public Value getValue(Session session) throws SQLException { 39 Value l = left.getValue(session); 40 if(l == ValueNull.INSTANCE) { 41 return l; 42 } 43 boolean result = false; 44 boolean hasNull = false; 45 for(int i=0; i<values.size(); i++) { 46 Expression e = (Expression) values.get(i); 47 Value r = e.getValue(session); 48 if(r == ValueNull.INSTANCE) { 49 hasNull = true; 50 } else { 51 result = Comparison.compareNotNull(database, l, r, Comparison.EQUAL); 52 if(result) { 53 break; 54 } 55 } 56 } 57 if(!result && hasNull) { 58 return ValueNull.INSTANCE; 59 } 60 return ValueBoolean.get(result); 61 } 62 63 public void mapColumns(ColumnResolver resolver, int queryLevel) throws SQLException { 64 left.mapColumns(resolver, queryLevel); 65 for(int i=0; i<values.size(); i++) { 66 Expression e = (Expression) values.get(i); 67 e.mapColumns(resolver, queryLevel); 68 } 69 this.queryLevel = Math.max(queryLevel, this.queryLevel); 70 } 71 72 public Expression optimize(Session session) throws SQLException { 73 left = left.optimize(session); 74 boolean constant = left.isConstant(); 75 if(constant && left == ValueExpression.NULL) { 76 return left; 77 } 78 boolean allValuesConstant = true; 79 for(int i=0; i<values.size(); i++) { 80 Expression e = (Expression) values.get(i); 81 e = e.optimize(session); 82 if(allValuesConstant && !e.isConstant()) { 83 allValuesConstant = false; 84 } 85 values.set(i, e); 86 } 87 if(constant && allValuesConstant) { 88 return ValueExpression.get(getValue(session)); 89 } 90 if(values.size()==1) { 92 Expression right = (Expression) values.get(0); 93 Expression expr = new Comparison(session, Comparison.EQUAL, left, right); 94 expr = expr.optimize(session); 95 return expr; 96 } 97 if(Constants.OPTIMIZE_IN) { 98 ExpressionVisitor independent = ExpressionVisitor.get(ExpressionVisitor.INDEPENDENT); 99 independent.queryLevel = queryLevel; 100 if(areAllValues(independent)) { 101 if(left instanceof ExpressionColumn) { 102 CompareMode mode = session.getDatabase().getCompareMode(); 103 for(int i=0; i<values.size(); i++) { 104 Expression e = (Expression) values.get(i); 105 Value v = e.getValue(session); 106 values.set(i, ValueExpression.get(v)); 107 if(min == null || min.compareTo(v, mode) > 0) { 108 min = v; 109 } 110 if(max == null || max.compareTo(v, mode) < 0) { 111 max = v; 112 } 113 } 114 } 115 } 116 } 117 return this; 118 } 119 120 public void createIndexConditions(TableFilter filter) { 121 if(!Constants.OPTIMIZE_IN) { 122 return; 123 } 124 if(min == null && max == null) { 125 return; 126 } 127 if(!(left instanceof ExpressionColumn)) { 128 return; 129 } 130 ExpressionColumn l = (ExpressionColumn)left; 131 if(filter != l.getTableFilter()) { 132 return; 133 } 134 filter.addIndexCondition(new IndexCondition(Comparison.BIGGER_EQUAL, l, ValueExpression.get(min))); 135 filter.addIndexCondition(new IndexCondition(Comparison.SMALLER_EQUAL, l, ValueExpression.get(max))); 136 } 137 138 public void setEvaluatable(TableFilter tableFilter, boolean b) { 139 left.setEvaluatable(tableFilter, b); 140 for(int i=0; i<values.size(); i++) { 141 Expression e = (Expression) values.get(i); 142 e.setEvaluatable(tableFilter, b); 143 } 144 } 145 146 public String getSQL() { 147 StringBuffer buff = new StringBuffer ("("); 148 buff.append(left.getSQL()); 149 buff.append(" IN("); 150 for(int i=0; i<values.size(); i++) { 151 if(i>0) { 152 buff.append(", "); 153 } 154 Expression e = (Expression) values.get(i); 155 buff.append(e.getSQL()); 156 } 157 buff.append("))"); 158 return buff.toString(); 159 } 160 161 public void updateAggregate(Session session) throws SQLException { 162 left.updateAggregate(session); 163 for(int i=0; i<values.size(); i++) { 164 Expression e = (Expression) values.get(i); 165 e.updateAggregate(session); 166 } 167 } 168 169 public boolean isEverything(ExpressionVisitor visitor) { 170 if(!left.isEverything(visitor)) { 171 return false; 172 } 173 return areAllValues(visitor); 174 } 175 176 private boolean areAllValues(ExpressionVisitor visitor) { 177 for(int i=0; i<values.size(); i++) { 178 Expression e = (Expression) values.get(i); 179 if(!e.isEverything(visitor)) { 180 return false; 181 } 182 } 183 return true; 184 } 185 186 public int getCost() { 187 int cost = left.getCost(); 188 for(int i=0; i<values.size(); i++) { 189 Expression e = (Expression) values.get(i); 190 cost += e.getCost(); 191 } 192 return cost; 193 } 194 195 } 196 | Popular Tags |