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

COVERAGE SUMMARY FOR SOURCE FILE [ExpressionColumn.java]

nameclass, %method, %block, %line, %
ExpressionColumn.java100% (1/1)100% (27/27)95%  (619/649)98%  (137.9/141)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ExpressionColumn100% (1/1)100% (27/27)95%  (619/649)98%  (137.9/141)
isEverything (ExpressionVisitor): boolean 100% (1/1)75%  (70/93)90%  (18/20)
updateAggregate (Session): void 100% (1/1)90%  (43/48)92%  (12/13)
getSQL (): String 100% (1/1)97%  (68/70)99%  (10.9/11)
ExpressionColumn (Database, Column): void 100% (1/1)100% (18/18)100% (7/7)
ExpressionColumn (Database, String, String, String): void 100% (1/1)100% (15/15)100% (6/6)
createIndexConditions (Session, TableFilter): void 100% (1/1)100% (22/22)100% (5/5)
getAlias (): String 100% (1/1)100% (26/26)100% (5/5)
getColumn (): Column 100% (1/1)100% (3/3)100% (1/1)
getColumnName (): String 100% (1/1)100% (10/10)100% (1/1)
getCost (): int 100% (1/1)100% (2/2)100% (1/1)
getDisplaySize (): int 100% (1/1)100% (4/4)100% (1/1)
getNotIfPossible (Session): Expression 100% (1/1)100% (10/10)100% (1/1)
getNullable (): int 100% (1/1)100% (8/8)100% (1/1)
getOriginalColumnName (): String 100% (1/1)100% (3/3)100% (1/1)
getOriginalTableAliasName (): String 100% (1/1)100% (3/3)100% (1/1)
getPrecision (): long 100% (1/1)100% (4/4)100% (1/1)
getScale (): int 100% (1/1)100% (4/4)100% (1/1)
getSchemaName (): String 100% (1/1)100% (12/12)100% (2/2)
getTableFilter (): TableFilter 100% (1/1)100% (9/9)100% (1/1)
getTableName (): String 100% (1/1)100% (11/11)100% (2/2)
getType (): int 100% (1/1)100% (4/4)100% (1/1)
getValue (Session): Value 100% (1/1)100% (41/41)100% (12/12)
isAutoIncrement (): boolean 100% (1/1)100% (8/8)100% (1/1)
mapColumn (ColumnResolver, Column, int): void 100% (1/1)100% (31/31)100% (8/8)
mapColumns (ColumnResolver, int): void 100% (1/1)100% (107/107)100% (21/21)
optimize (Session): Expression 100% (1/1)100% (71/71)100% (13/13)
setEvaluatable (TableFilter, boolean): void 100% (1/1)100% (12/12)100% (3/3)

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.HashMap;
9 
10import org.h2.api.ErrorCode;
11import org.h2.command.Parser;
12import org.h2.command.dml.Select;
13import org.h2.command.dml.SelectListColumnResolver;
14import org.h2.engine.Database;
15import org.h2.engine.Session;
16import org.h2.index.IndexCondition;
17import org.h2.message.DbException;
18import org.h2.schema.Constant;
19import org.h2.schema.Schema;
20import org.h2.table.Column;
21import org.h2.table.ColumnResolver;
22import org.h2.table.Table;
23import org.h2.table.TableFilter;
24import org.h2.value.Value;
25import org.h2.value.ValueBoolean;
26 
27/**
28 * A expression that represents a column of a table or view.
29 */
30public class ExpressionColumn extends Expression {
31 
32    private final Database database;
33    private final String schemaName;
34    private final String tableAlias;
35    private final String columnName;
36    private ColumnResolver columnResolver;
37    private int queryLevel;
38    private Column column;
39    private boolean evaluatable;
40 
41    public ExpressionColumn(Database database, Column column) {
42        this.database = database;
43        this.column = column;
44        this.schemaName = null;
45        this.tableAlias = null;
46        this.columnName = null;
47    }
48 
49    public ExpressionColumn(Database database, String schemaName,
50            String tableAlias, String columnName) {
51        this.database = database;
52        this.schemaName = schemaName;
53        this.tableAlias = tableAlias;
54        this.columnName = columnName;
55    }
56 
57    @Override
58    public String getSQL() {
59        String sql;
60        boolean quote = database.getSettings().databaseToUpper;
61        if (column != null) {
62            sql = column.getSQL();
63        } else {
64            sql = quote ? Parser.quoteIdentifier(columnName) : columnName;
65        }
66        if (tableAlias != null) {
67            String a = quote ? Parser.quoteIdentifier(tableAlias) : tableAlias;
68            sql = a + "." + sql;
69        }
70        if (schemaName != null) {
71            String s = quote ? Parser.quoteIdentifier(schemaName) : schemaName;
72            sql = s + "." + sql;
73        }
74        return sql;
75    }
76 
77    public TableFilter getTableFilter() {
78        return columnResolver == null ? null : columnResolver.getTableFilter();
79    }
80 
81    @Override
82    public void mapColumns(ColumnResolver resolver, int level) {
83        if (tableAlias != null && !database.equalsIdentifiers(
84                tableAlias, resolver.getTableAlias())) {
85            return;
86        }
87        if (schemaName != null && !database.equalsIdentifiers(
88                schemaName, resolver.getSchemaName())) {
89            return;
90        }
91        for (Column col : resolver.getColumns()) {
92            String n = col.getName();
93            if (database.equalsIdentifiers(columnName, n)) {
94                mapColumn(resolver, col, level);
95                return;
96            }
97        }
98        if (database.equalsIdentifiers(Column.ROWID, columnName)) {
99            Column col = resolver.getRowIdColumn();
100            if (col != null) {
101                mapColumn(resolver, col, level);
102                return;
103            }
104        }
105        Column[] columns = resolver.getSystemColumns();
106        for (int i = 0; columns != null && i < columns.length; i++) {
107            Column col = columns[i];
108            if (database.equalsIdentifiers(columnName, col.getName())) {
109                mapColumn(resolver, col, level);
110                return;
111            }
112        }
113    }
114 
115    private void mapColumn(ColumnResolver resolver, Column col, int level) {
116        if (this.columnResolver == null) {
117            queryLevel = level;
118            column = col;
119            this.columnResolver = resolver;
120        } else if (queryLevel == level && this.columnResolver != resolver) {
121            if (resolver instanceof SelectListColumnResolver) {
122                // ignore - already mapped, that's ok
123            } else {
124                throw DbException.get(ErrorCode.AMBIGUOUS_COLUMN_NAME_1, columnName);
125            }
126        }
127    }
128 
129    @Override
130    public Expression optimize(Session session) {
131        if (columnResolver == null) {
132            Schema schema = session.getDatabase().findSchema(
133                    tableAlias == null ? session.getCurrentSchemaName() : tableAlias);
134            if (schema != null) {
135                Constant constant = schema.findConstant(columnName);
136                if (constant != null) {
137                    return constant.getValue();
138                }
139            }
140            String name = columnName;
141            if (tableAlias != null) {
142                name = tableAlias + "." + name;
143                if (schemaName != null) {
144                    name = schemaName + "." + name;
145                }
146            }
147            throw DbException.get(ErrorCode.COLUMN_NOT_FOUND_1, name);
148        }
149        return columnResolver.optimize(this, column);
150    }
151 
152    @Override
153    public void updateAggregate(Session session) {
154        Value now = columnResolver.getValue(column);
155        Select select = columnResolver.getSelect();
156        if (select == null) {
157            throw DbException.get(ErrorCode.MUST_GROUP_BY_COLUMN_1, getSQL());
158        }
159        HashMap<Expression, Object> values = select.getCurrentGroup();
160        if (values == null) {
161            // this is a different level (the enclosing query)
162            return;
163        }
164        Value v = (Value) values.get(this);
165        if (v == null) {
166            values.put(this, now);
167        } else {
168            if (!database.areEqual(now, v)) {
169                throw DbException.get(ErrorCode.MUST_GROUP_BY_COLUMN_1, getSQL());
170            }
171        }
172    }
173 
174    @Override
175    public Value getValue(Session session) {
176        Select select = columnResolver.getSelect();
177        if (select != null) {
178            HashMap<Expression, Object> values = select.getCurrentGroup();
179            if (values != null) {
180                Value v = (Value) values.get(this);
181                if (v != null) {
182                    return v;
183                }
184            }
185        }
186        Value value = columnResolver.getValue(column);
187        if (value == null) {
188            columnResolver.getValue(column);
189            throw DbException.get(ErrorCode.MUST_GROUP_BY_COLUMN_1, getSQL());
190        }
191        return value;
192    }
193 
194    @Override
195    public int getType() {
196        return column.getType();
197    }
198 
199    @Override
200    public void setEvaluatable(TableFilter tableFilter, boolean b) {
201        if (columnResolver != null && tableFilter == columnResolver.getTableFilter()) {
202            evaluatable = b;
203        }
204    }
205 
206    public Column getColumn() {
207        return column;
208    }
209 
210    @Override
211    public int getScale() {
212        return column.getScale();
213    }
214 
215    @Override
216    public long getPrecision() {
217        return column.getPrecision();
218    }
219 
220    @Override
221    public int getDisplaySize() {
222        return column.getDisplaySize();
223    }
224 
225    public String getOriginalColumnName() {
226        return columnName;
227    }
228 
229    public String getOriginalTableAliasName() {
230        return tableAlias;
231    }
232 
233    @Override
234    public String getColumnName() {
235        return columnName != null ? columnName : column.getName();
236    }
237 
238    @Override
239    public String getSchemaName() {
240        Table table = column.getTable();
241        return table == null ? null : table.getSchema().getName();
242    }
243 
244    @Override
245    public String getTableName() {
246        Table table = column.getTable();
247        return table == null ? null : table.getName();
248    }
249 
250    @Override
251    public String getAlias() {
252        if (column != null) {
253            return column.getName();
254        }
255        if (tableAlias != null) {
256            return tableAlias + "." + columnName;
257        }
258        return columnName;
259    }
260 
261    @Override
262    public boolean isAutoIncrement() {
263        return column.getSequence() != null;
264    }
265 
266    @Override
267    public int getNullable() {
268        return column.isNullable() ? Column.NULLABLE : Column.NOT_NULLABLE;
269    }
270 
271    @Override
272    public boolean isEverything(ExpressionVisitor visitor) {
273        switch (visitor.getType()) {
274        case ExpressionVisitor.OPTIMIZABLE_MIN_MAX_COUNT_ALL:
275            return false;
276        case ExpressionVisitor.READONLY:
277        case ExpressionVisitor.DETERMINISTIC:
278        case ExpressionVisitor.QUERY_COMPARABLE:
279            return true;
280        case ExpressionVisitor.INDEPENDENT:
281            return this.queryLevel < visitor.getQueryLevel();
282        case ExpressionVisitor.EVALUATABLE:
283            // if the current value is known (evaluatable set)
284            // or if this columns belongs to a 'higher level' query and is
285            // therefore just a parameter
286            if (database.getSettings().nestedJoins) {
287                if (visitor.getQueryLevel() < this.queryLevel) {
288                    return true;
289                }
290                if (getTableFilter() == null) {
291                    return false;
292                }
293                return getTableFilter().isEvaluatable();
294            }
295            return evaluatable || visitor.getQueryLevel() < this.queryLevel;
296        case ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID:
297            visitor.addDataModificationId(column.getTable().getMaxDataModificationId());
298            return true;
299        case ExpressionVisitor.NOT_FROM_RESOLVER:
300            return columnResolver != visitor.getResolver();
301        case ExpressionVisitor.GET_DEPENDENCIES:
302            if (column != null) {
303                visitor.addDependency(column.getTable());
304            }
305            return true;
306        case ExpressionVisitor.GET_COLUMNS:
307            visitor.addColumn(column);
308            return true;
309        default:
310            throw DbException.throwInternalError("type=" + visitor.getType());
311        }
312    }
313 
314    @Override
315    public int getCost() {
316        return 2;
317    }
318 
319    @Override
320    public void createIndexConditions(Session session, TableFilter filter) {
321        TableFilter tf = getTableFilter();
322        if (filter == tf && column.getType() == Value.BOOLEAN) {
323            IndexCondition cond = IndexCondition.get(
324                    Comparison.EQUAL, this, ValueExpression.get(
325                            ValueBoolean.get(true)));
326            filter.addIndexCondition(cond);
327        }
328    }
329 
330    @Override
331    public Expression getNotIfPossible(Session session) {
332        return new Comparison(session, Comparison.EQUAL, this,
333                ValueExpression.get(ValueBoolean.get(false)));
334    }
335 
336}

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