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

COVERAGE SUMMARY FOR SOURCE FILE [JavaAggregate.java]

nameclass, %method, %block, %line, %
JavaAggregate.java100% (1/1)93%  (13/14)84%  (309/369)78%  (68/87)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class JavaAggregate100% (1/1)93%  (13/14)84%  (309/369)78%  (68/87)
getCost (): int 0%   (0/1)0%   (0/26)0%   (0/4)
getValue (Session): Value 100% (1/1)63%  (24/38)58%  (7/12)
isEverything (ExpressionVisitor): boolean 100% (1/1)81%  (30/37)62%  (5/8)
updateAggregate (Session): void 100% (1/1)90%  (82/91)80%  (20/25)
optimize (Session): Expression 100% (1/1)93%  (52/56)86%  (12/14)
JavaAggregate (UserAggregate, Expression [], Select): void 100% (1/1)100% (12/12)100% (5/5)
getDisplaySize (): int 100% (1/1)100% (2/2)100% (1/1)
getInstance (): Aggregate 100% (1/1)100% (10/10)100% (3/3)
getPrecision (): long 100% (1/1)100% (2/2)100% (1/1)
getSQL (): String 100% (1/1)100% (43/43)100% (6/6)
getScale (): int 100% (1/1)100% (5/5)100% (1/1)
getType (): int 100% (1/1)100% (3/3)100% (1/1)
mapColumns (ColumnResolver, int): void 100% (1/1)100% (22/22)100% (3/3)
setEvaluatable (TableFilter, boolean): void 100% (1/1)100% (22/22)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.sql.Connection;
9import java.sql.SQLException;
10import java.util.HashMap;
11import org.h2.api.Aggregate;
12import org.h2.api.ErrorCode;
13import org.h2.command.Parser;
14import org.h2.command.dml.Select;
15import org.h2.engine.Session;
16import org.h2.engine.UserAggregate;
17import org.h2.message.DbException;
18import org.h2.table.ColumnResolver;
19import org.h2.table.TableFilter;
20import org.h2.util.StatementBuilder;
21import org.h2.value.DataType;
22import org.h2.value.Value;
23import org.h2.value.ValueNull;
24 
25/**
26 * This class wraps a user-defined aggregate.
27 */
28public class JavaAggregate extends Expression {
29 
30    private final UserAggregate userAggregate;
31    private final Select select;
32    private final Expression[] args;
33    private int[] argTypes;
34    private int dataType;
35    private Connection userConnection;
36    private int lastGroupRowId;
37 
38    public JavaAggregate(UserAggregate userAggregate, Expression[] args,
39            Select select) {
40        this.userAggregate = userAggregate;
41        this.args = args;
42        this.select = select;
43    }
44 
45    @Override
46    public int getCost() {
47        int cost = 5;
48        for (Expression e : args) {
49            cost += e.getCost();
50        }
51        return cost;
52    }
53 
54    @Override
55    public long getPrecision() {
56        return Integer.MAX_VALUE;
57    }
58 
59    @Override
60    public int getDisplaySize() {
61        return Integer.MAX_VALUE;
62    }
63 
64    @Override
65    public int getScale() {
66        return DataType.getDataType(dataType).defaultScale;
67    }
68 
69    @Override
70    public String getSQL() {
71        StatementBuilder buff = new StatementBuilder();
72        buff.append(Parser.quoteIdentifier(userAggregate.getName())).append('(');
73        for (Expression e : args) {
74            buff.appendExceptFirst(", ");
75            buff.append(e.getSQL());
76        }
77        return buff.append(')').toString();
78    }
79 
80    @Override
81    public int getType() {
82        return dataType;
83    }
84 
85    @Override
86    public boolean isEverything(ExpressionVisitor visitor) {
87        switch(visitor.getType()) {
88        case ExpressionVisitor.DETERMINISTIC:
89            // TODO optimization: some functions are deterministic, but we don't
90            // know (no setting for that)
91        case ExpressionVisitor.OPTIMIZABLE_MIN_MAX_COUNT_ALL:
92            // user defined aggregate functions can not be optimized
93            return false;
94        case ExpressionVisitor.GET_DEPENDENCIES:
95            visitor.addDependency(userAggregate);
96            break;
97        default:
98        }
99        for (Expression e : args) {
100            if (e != null && !e.isEverything(visitor)) {
101                return false;
102            }
103        }
104        return true;
105    }
106 
107    @Override
108    public void mapColumns(ColumnResolver resolver, int level) {
109        for (Expression arg : args) {
110            arg.mapColumns(resolver, level);
111        }
112    }
113 
114    @Override
115    public Expression optimize(Session session) {
116        userConnection = session.createConnection(false);
117        int len = args.length;
118        argTypes = new int[len];
119        for (int i = 0; i < len; i++) {
120            Expression expr = args[i];
121            args[i] = expr.optimize(session);
122            int type = expr.getType();
123            argTypes[i] = type;
124        }
125        try {
126            Aggregate aggregate = getInstance();
127            dataType = aggregate.getInternalType(argTypes);
128        } catch (SQLException e) {
129            throw DbException.convert(e);
130        }
131        return this;
132    }
133 
134    @Override
135    public void setEvaluatable(TableFilter tableFilter, boolean b) {
136        for (Expression e : args) {
137            e.setEvaluatable(tableFilter, b);
138        }
139    }
140 
141    private Aggregate getInstance() throws SQLException {
142        Aggregate agg = userAggregate.getInstance();
143        agg.init(userConnection);
144        return agg;
145    }
146 
147    @Override
148    public Value getValue(Session session) {
149        HashMap<Expression, Object> group = select.getCurrentGroup();
150        if (group == null) {
151            throw DbException.get(ErrorCode.INVALID_USE_OF_AGGREGATE_FUNCTION_1, getSQL());
152        }
153        try {
154            Aggregate agg = (Aggregate) group.get(this);
155            if (agg == null) {
156                agg = getInstance();
157            }
158            Object obj = agg.getResult();
159            if (obj == null) {
160                return ValueNull.INSTANCE;
161            }
162            return DataType.convertToValue(session, obj, dataType);
163        } catch (SQLException e) {
164            throw DbException.convert(e);
165        }
166    }
167 
168    @Override
169    public void updateAggregate(Session session) {
170        HashMap<Expression, Object> group = select.getCurrentGroup();
171        if (group == null) {
172            // this is a different level (the enclosing query)
173            return;
174        }
175 
176        int groupRowId = select.getCurrentGroupRowId();
177        if (lastGroupRowId == groupRowId) {
178            // already visited
179            return;
180        }
181        lastGroupRowId = groupRowId;
182 
183        Aggregate agg = (Aggregate) group.get(this);
184        try {
185            if (agg == null) {
186                agg = getInstance();
187                group.put(this, agg);
188            }
189            Object[] argValues = new Object[args.length];
190            Object arg = null;
191            for (int i = 0, len = args.length; i < len; i++) {
192                Value v = args[i].getValue(session);
193                v = v.convertTo(argTypes[i]);
194                arg = v.getObject();
195                argValues[i] = arg;
196            }
197            if (args.length == 1) {
198                agg.add(arg);
199            } else {
200                agg.add(argValues);
201            }
202        } catch (SQLException e) {
203            throw DbException.convert(e);
204        }
205    }
206 
207}

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