EMMA Coverage Report (generated Sun Mar 01 22:06:14 CET 2015)
[all classes][org.h2.index]

COVERAGE SUMMARY FOR SOURCE FILE [IndexCondition.java]

nameclass, %method, %block, %line, %
IndexCondition.java100% (2/2)100% (19/19)93%  (343/369)96%  (91/95)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class IndexCondition100% (1/1)100% (17/17)93%  (328/354)96%  (90/94)
getMask (ArrayList): int 100% (1/1)67%  (26/39)82%  (9/11)
isEquality (boolean): boolean 100% (1/1)87%  (13/15)67%  (2/3)
getSQL (): String 100% (1/1)91%  (110/121)97%  (33/34)
IndexCondition (int, ExpressionColumn, Expression): void 100% (1/1)100% (17/17)100% (5/5)
get (int, ExpressionColumn, Expression): IndexCondition 100% (1/1)100% (7/7)100% (1/1)
getColumn (): Column 100% (1/1)100% (3/3)100% (1/1)
getCompareType (): int 100% (1/1)100% (3/3)100% (1/1)
getCurrentResult (): ResultInterface 100% (1/1)100% (5/5)100% (1/1)
getCurrentValue (Session): Value 100% (1/1)100% (5/5)100% (1/1)
getCurrentValueList (Session): Value [] 100% (1/1)100% (50/50)100% (11/11)
getInList (ExpressionColumn, List): IndexCondition 100% (1/1)100% (12/12)100% (3/3)
getInQuery (ExpressionColumn, Query): IndexCondition 100% (1/1)100% (12/12)100% (3/3)
isAlwaysFalse (): boolean 100% (1/1)100% (8/8)100% (1/1)
isEnd (): boolean 100% (1/1)100% (7/7)100% (3/3)
isEvaluatable (): boolean 100% (1/1)100% (36/36)100% (9/9)
isSpatialIntersects (): boolean 100% (1/1)100% (7/7)100% (3/3)
isStart (): boolean 100% (1/1)100% (7/7)100% (3/3)
     
class IndexCondition$1100% (1/1)100% (2/2)100% (15/15)100% (2/2)
IndexCondition$1 (IndexCondition, CompareMode): void 100% (1/1)100% (9/9)100% (1/1)
compare (Value, Value): int 100% (1/1)100% (6/6)100% (1/1)

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

[all classes][org.h2.index]
EMMA 2.0.5312 (C) Vladimir Roubtsov