File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\expression\ConditionIn.java.html

1 /*
2 * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
3 * Version 1.0, and under the Eclipse Public License, Version 1.0
4 * (http://h2database.com/html/license.html).
5 * Initial Developer: H2 Group
6 */
7 package org.h2.expression;
8
9 import java.util.ArrayList;
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.StatementBuilder;
16 import org.h2.value.Value;
17 import org.h2.value.ValueBoolean;
18 import org.h2.value.ValueNull;
19
20 /**
21 * An 'in' condition with a list of values, as in WHERE NAME IN(...)
22 */
23 public class ConditionIn extends Condition {
24
25 private final Database database;
26 private Expression left;
27 private final ArrayList<Expression> valueList;
28 private int queryLevel;
29
30 /**
31 * Create a new IN(..) condition.
32 *
33 * @param database the database
34 * @param left the expression before IN
35 * @param values the value list (at least one element)
36 */
37 public ConditionIn(Database database, Expression left, ArrayList<Expression> values) {
38 this.database = database;
39 this.left = left;
40 this.valueList = values;
41 }
42
43 public Value getValue(Session session) {
44 Value l = left.getValue(session);
45 if (l == ValueNull.INSTANCE) {
46 return l;
47 }
48 boolean result = false;
49 boolean hasNull = false;
50 for (Expression e : valueList) {
51 Value r = e.getValue(session);
52 if (r == ValueNull.INSTANCE) {
53 hasNull = true;
54 } else {
55 r = r.convertTo(l.getType());
56 result = Comparison.compareNotNull(database, l, r, Comparison.EQUAL);
57 if (result) {
58 break;
59 }
60 }
61 }
62 if (!result && hasNull) {
63 return ValueNull.INSTANCE;
64 }
65 return ValueBoolean.get(result);
66 }
67
68 public void mapColumns(ColumnResolver resolver, int level) {
69 left.mapColumns(resolver, level);
70 for (Expression e : valueList) {
71 e.mapColumns(resolver, level);
72 }
73 this.queryLevel = Math.max(level, this.queryLevel);
74 }
75
76 public Expression optimize(Session session) {
77 left = left.optimize(session);
78 boolean constant = left.isConstant();
79 if (constant && left == ValueExpression.getNull()) {
80 return left;
81 }
82 boolean allValuesConstant = true;
83 boolean allValuesSameType = true;
84 int size = valueList.size();
85 Expression lastExpr = null;
86 for (int i = 0; i < size; i++) {
87 Expression e = valueList.get(i);
88 e = e.optimize(session);
89 if (allValuesConstant && !e.isConstant()) {
90 allValuesConstant = false;
91 }
92 valueList.set(i, e);
93 if (lastExpr != null && lastExpr.getType() != e.getType()) {
94 allValuesSameType = false;
95 }
96 lastExpr = e;
97 }
98 if (constant && allValuesConstant) {
99 return ValueExpression.get(getValue(session));
100 }
101 if (size == 1) {
102 Expression right = valueList.get(0);
103 Expression expr = new Comparison(session, Comparison.EQUAL, left, right);
104 expr = expr.optimize(session);
105 return expr;
106 }
107 if (allValuesConstant && allValuesSameType) {
108 Expression expr = new ConditionInConstantSet(session, left, valueList);
109 expr = expr.optimize(session);
110 return expr;
111 }
112 return this;
113 }
114
115 public void createIndexConditions(Session session, TableFilter filter) {
116 if (!(left instanceof ExpressionColumn)) {
117 return;
118 }
119 ExpressionColumn l = (ExpressionColumn) left;
120 if (filter != l.getTableFilter()) {
121 return;
122 }
123 if (session.getDatabase().getSettings().optimizeInList) {
124 ExpressionVisitor visitor = ExpressionVisitor.getNotFromResolverVisitor(filter);
125 for (Expression e : valueList) {
126 if (!e.isEverything(visitor)) {
127 return;
128 }
129 }
130 filter.addIndexCondition(IndexCondition.getInList(l, valueList));
131 return;
132 }
133 }
134
135 public void setEvaluatable(TableFilter tableFilter, boolean b) {
136 left.setEvaluatable(tableFilter, b);
137 for (Expression e : valueList) {
138 e.setEvaluatable(tableFilter, b);
139 }
140 }
141
142 public String getSQL() {
143 StatementBuilder buff = new StatementBuilder("(");
144 buff.append(left.getSQL()).append(" IN(");
145 for (Expression e : valueList) {
146 buff.appendExceptFirst(", ");
147 buff.append(e.getSQL());
148 }
149 return buff.append("))").toString();
150 }
151
152 public void updateAggregate(Session session) {
153 left.updateAggregate(session);
154 for (Expression e : valueList) {
155 e.updateAggregate(session);
156 }
157 }
158
159 public boolean isEverything(ExpressionVisitor visitor) {
160 if (!left.isEverything(visitor)) {
161 return false;
162 }
163 return areAllValues(visitor);
164 }
165
166 private boolean areAllValues(ExpressionVisitor visitor) {
167 for (Expression e : valueList) {
168 if (!e.isEverything(visitor)) {
169 return false;
170 }
171 }
172 return true;
173 }
174
175 public int getCost() {
176 int cost = left.getCost();
177 for (Expression e : valueList) {
178 cost += e.getCost();
179 }
180 return cost;
181 }
182
183 /**
184 * Add an additional element if possible. Example: given two conditions
185 * A IN(1, 2) OR A=3, the constant 3 is added: A IN(1, 2, 3).
186 *
187 * @param other the second condition
188 * @return null if the condition was not added, or the new condition
189 */
190 Expression getAdditional(Comparison other) {
191 Expression add = other.getIfEquals(left);
192 if (add != null) {
193 valueList.add(add);
194 return this;
195 }
196 return null;
197 }
198 }
199