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

COVERAGE SUMMARY FOR SOURCE FILE [ConditionIn.java]

nameclass, %method, %block, %line, %
ConditionIn.java100% (1/1)85%  (11/13)94%  (415/443)91%  (100/110)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ConditionIn100% (1/1)85%  (11/13)94%  (415/443)91%  (100/110)
isDisjunctive (): boolean 0%   (0/1)0%   (0/2)0%   (0/1)
updateAggregate (Session): void 0%   (0/1)0%   (0/20)0%   (0/5)
isEverything (ExpressionVisitor): boolean 100% (1/1)82%  (9/11)67%  (2/3)
createIndexConditions (Session, TableFilter): void 100% (1/1)96%  (45/47)86%  (12/14)
optimize (Session): Expression 100% (1/1)99%  (142/144)97%  (31/32)
ConditionIn (Database, Expression, ArrayList): void 100% (1/1)100% (12/12)100% (5/5)
areAllValues (ExpressionVisitor): boolean 100% (1/1)100% (20/20)100% (5/5)
getAdditional (Comparison): Expression 100% (1/1)100% (16/16)100% (5/5)
getCost (): int 100% (1/1)100% (23/23)100% (5/5)
getSQL (): String 100% (1/1)100% (38/38)100% (7/7)
getValue (Session): Value 100% (1/1)100% (60/60)100% (17/17)
mapColumns (ColumnResolver, int): void 100% (1/1)100% (28/28)100% (6/6)
setEvaluatable (TableFilter, boolean): void 100% (1/1)100% (22/22)100% (5/5)

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

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