File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\index\IndexCondition.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.index;
8
9 import java.util.ArrayList;
10 import java.util.Arrays;
11 import java.util.Comparator;
12 import java.util.HashSet;
13 import java.util.List;
14 import org.h2.command.dml.Query;
15 import org.h2.engine.Session;
16 import org.h2.expression.Comparison;
17 import org.h2.expression.Expression;
18 import org.h2.expression.ExpressionColumn;
19 import org.h2.expression.ExpressionVisitor;
20 import org.h2.message.DbException;
21 import org.h2.result.ResultInterface;
22 import org.h2.table.Column;
23 import org.h2.table.Table;
24 import org.h2.util.StatementBuilder;
25 import org.h2.value.CompareMode;
26 import org.h2.value.Value;
27
28 /**
29 * A index condition object is made for each condition that can potentially use
30 * an index. This class does not extend expression, but in general there is one
31 * expression that maps to each index condition.
32 */
33 public class IndexCondition {
34
35 /**
36 * A bit of a search mask meaning 'equal'.
37 */
38 public static final int EQUALITY = 1;
39
40 /**
41 * A bit of a search mask meaning 'larger or equal'.
42 */
43 public static final int START = 2;
44
45 /**
46 * A bit of a search mask meaning 'smaller or equal'.
47 */
48 public static final int END = 4;
49
50 /**
51 * A search mask meaning 'between'.
52 */
53 public static final int RANGE = START | END;
54
55 /**
56 * A bit of a search mask meaning 'the condition is always false'.
57 */
58 public static final int ALWAYS_FALSE = 8;
59
60 private final Column column;
61 private final int compareType;
62
63 private final Expression expression;
64 private List<Expression> expressionList;
65 private Query expressionQuery;
66
67 private IndexCondition(int compareType, ExpressionColumn column, Expression expression) {
68 this.compareType = compareType;
69 this.column = column == null ? null : column.getColumn();
70 this.expression = expression;
71 }
72
73 /**
74 * Create an index condition with the given parameters.
75 *
76 * @param compareType the comparison type
77 * @param column the column
78 * @param expression the expression
79 * @return the index condition
80 */
81 public static IndexCondition get(int compareType, ExpressionColumn column, Expression expression) {
82 return new IndexCondition(compareType, column, expression);
83 }
84
85 /**
86 * Create an index condition with the compare type IN_LIST and with the
87 * given parameters.
88 *
89 * @param column the column
90 * @param list the expression list
91 * @return the index condition
92 */
93 public static IndexCondition getInList(ExpressionColumn column, List<Expression> list) {
94 IndexCondition cond = new IndexCondition(Comparison.IN_LIST, column, null);
95 cond.expressionList = list;
96 return cond;
97 }
98
99 /**
100 * Create an index condition with the compare type IN_QUERY and with the
101 * given parameters.
102 *
103 * @param column the column
104 * @param query the select statement
105 * @return the index condition
106 */
107 public static IndexCondition getInQuery(ExpressionColumn column, Query query) {
108 IndexCondition cond = new IndexCondition(Comparison.IN_QUERY, column, null);
109 cond.expressionQuery = query;
110 return cond;
111 }
112
113 /**
114 * Get the current value of the expression.
115 *
116 * @param session the session
117 * @return the value
118 */
119 public Value getCurrentValue(Session session) {
120 return expression.getValue(session);
121 }
122
123 /**
124 * Get the current value list of the expression. The value list is of the
125 * same type as the column, distinct, and sorted.
126 *
127 * @param session the session
128 * @return the value list
129 */
130 public Value[] getCurrentValueList(Session session) {
131 HashSet<Value> valueSet = new HashSet<Value>();
132 for (Expression e : expressionList) {
133 Value v = e.getValue(session);
134 v = column.convert(v);
135 valueSet.add(v);
136 }
137 Value[] array = new Value[valueSet.size()];
138 valueSet.toArray(array);
139 final CompareMode mode = session.getDatabase().getCompareMode();
140 Arrays.sort(array, new Comparator<Value>() {
141 public int compare(Value o1, Value o2) {
142 return o1.compareTo(o2, mode);
143 }
144 });
145 return array;
146 }
147
148 /**
149 * Get the current result of the expression. The rows may not be of the same
150 * type, therefore the rows may not be unique.
151 *
152 * @return the result
153 */
154 public ResultInterface getCurrentResult() {
155 return expressionQuery.query(0);
156 }
157
158 /**
159 * Get the SQL snippet of this comparison.
160 *
161 * @return the SQL snippet
162 */
163 public String getSQL() {
164 if (compareType == Comparison.FALSE) {
165 return "FALSE";
166 }
167 StatementBuilder buff = new StatementBuilder();
168 buff.append(column.getSQL());
169 switch(compareType) {
170 case Comparison.EQUAL:
171 buff.append(" = ");
172 break;
173 case Comparison.EQUAL_NULL_SAFE:
174 buff.append(" IS ");
175 break;
176 case Comparison.BIGGER_EQUAL:
177 buff.append(" >= ");
178 break;
179 case Comparison.BIGGER:
180 buff.append(" > ");
181 break;
182 case Comparison.SMALLER_EQUAL:
183 buff.append(" <= ");
184 break;
185 case Comparison.SMALLER:
186 buff.append(" < ");
187 break;
188 case Comparison.IN_LIST:
189 buff.append(" IN(");
190 for (Expression e : expressionList) {
191 buff.appendExceptFirst(", ");
192 buff.append(e.getSQL());
193 }
194 buff.append(')');
195 break;
196 case Comparison.IN_QUERY:
197 buff.append(" IN(");
198 buff.append(expressionQuery.getPlanSQL());
199 buff.append(')');
200 break;
201 default:
202 DbException.throwInternalError("type="+compareType);
203 }
204 if (expression != null) {
205 buff.append(expression.getSQL());
206 }
207 return buff.toString();
208 }
209
210 /**
211 * Get the comparison bit mask.
212 *
213 * @param indexConditions all index conditions
214 * @return the mask
215 */
216 public int getMask(ArrayList<IndexCondition> indexConditions) {
217 switch (compareType) {
218 case Comparison.FALSE:
219 return ALWAYS_FALSE;
220 case Comparison.EQUAL:
221 case Comparison.EQUAL_NULL_SAFE:
222 return EQUALITY;
223 case Comparison.IN_LIST:
224 case Comparison.IN_QUERY:
225 if (indexConditions.size() > 1) {
226 if (!Table.TABLE.equals(column.getTable().getTableType())) {
227 // if combined with other conditions,
228 // IN(..) can only be used for regular tables
229 // test case:
230 // create table test(a int, b int, primary key(id, name));
231 // create unique index c on test(b, a);
232 // insert into test values(1, 10), (2, 20);
233 // select * from (select * from test)
234 // where a=1 and b in(10, 20);
235 return 0;
236 }
237 }
238 return EQUALITY;
239 case Comparison.BIGGER_EQUAL:
240 case Comparison.BIGGER:
241 return START;
242 case Comparison.SMALLER_EQUAL:
243 case Comparison.SMALLER:
244 return END;
245 default:
246 throw DbException.throwInternalError("type=" + compareType);
247 }
248 }
249
250 /**
251 * Check if the result is always false.
252 *
253 * @return true if the result will always be false
254 */
255 public boolean isAlwaysFalse() {
256 return compareType == Comparison.FALSE;
257 }
258
259 /**
260 * Check if this index condition is of the type column larger or equal to
261 * value.
262 *
263 * @return true if this is a start condition
264 */
265 public boolean isStart() {
266 switch (compareType) {
267 case Comparison.EQUAL:
268 case Comparison.EQUAL_NULL_SAFE:
269 case Comparison.BIGGER_EQUAL:
270 case Comparison.BIGGER:
271 return true;
272 default:
273 return false;
274 }
275 }
276
277 /**
278 * Check if this index condition is of the type column smaller or equal to
279 * value.
280 *
281 * @return true if this is a end condition
282 */
283 public boolean isEnd() {
284 switch (compareType) {
285 case Comparison.EQUAL:
286 case Comparison.EQUAL_NULL_SAFE:
287 case Comparison.SMALLER_EQUAL:
288 case Comparison.SMALLER:
289 return true;
290 default:
291 return false;
292 }
293 }
294
295 public int getCompareType() {
296 return compareType;
297 }
298
299 /**
300 * Get the referenced column.
301 *
302 * @return the column
303 */
304 public Column getColumn() {
305 return column;
306 }
307
308 /**
309 * Check if the expression can be evaluated.
310 *
311 * @return true if it can be evaluated
312 */
313 public boolean isEvaluatable() {
314 if (expression != null) {
315 return expression.isEverything(ExpressionVisitor.EVALUATABLE_VISITOR);
316 }
317 if (expressionList != null) {
318 for (Expression e : expressionList) {
319 if (!e.isEverything(ExpressionVisitor.EVALUATABLE_VISITOR)) {
320 return false;
321 }
322 }
323 return true;
324 }
325 return expressionQuery.isEverything(ExpressionVisitor.EVALUATABLE_VISITOR);
326 }
327
328 }
329