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

COVERAGE SUMMARY FOR SOURCE FILE [FunctionTable.java]

nameclass, %method, %block, %line, %
FunctionTable.java100% (1/1)43%  (13/30)76%  (221/289)66%  (48.6/74)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class FunctionTable100% (1/1)43%  (13/30)76%  (221/289)66%  (48.6/74)
addIndex (Session, String, int, IndexColumn [], IndexType, boolean, String): ... 0%   (0/1)0%   (0/3)0%   (0/1)
addRow (Session, Row): void 0%   (0/1)0%   (0/3)0%   (0/1)
canDrop (): boolean 0%   (0/1)0%   (0/2)0%   (0/1)
canReference (): boolean 0%   (0/1)0%   (0/2)0%   (0/1)
checkRename (): void 0%   (0/1)0%   (0/3)0%   (0/1)
checkSupportAlter (): void 0%   (0/1)0%   (0/3)0%   (0/1)
close (Session): void 0%   (0/1)0%   (0/1)0%   (0/1)
getCreateSQL (): String 0%   (0/1)0%   (0/2)0%   (0/1)
getDiskSpaceUsed (): long 0%   (0/1)0%   (0/2)0%   (0/1)
getDropSQL (): String 0%   (0/1)0%   (0/2)0%   (0/1)
getRowCount (Session): long 0%   (0/1)0%   (0/3)0%   (0/1)
getRowCountApproximation (): long 0%   (0/1)0%   (0/3)0%   (0/1)
getUniqueIndex (): Index 0%   (0/1)0%   (0/2)0%   (0/1)
isLockedExclusively (): boolean 0%   (0/1)0%   (0/2)0%   (0/1)
removeRow (Session, Row): void 0%   (0/1)0%   (0/3)0%   (0/1)
truncate (Session): void 0%   (0/1)0%   (0/3)0%   (0/1)
unlock (Session): void 0%   (0/1)0%   (0/1)0%   (0/1)
canGetRowCount (): boolean 100% (1/1)78%  (7/9)77%  (0.8/1)
getResult (Session): ResultInterface 100% (1/1)79%  (31/39)73%  (8/11)
getResultSet (Session): ResultSet 100% (1/1)82%  (9/11)90%  (1.8/2)
getValueResultSet (Session): ValueResultSet 100% (1/1)89%  (17/19)80%  (4/5)
FunctionTable (Schema, Session, Expression, FunctionCall): void 100% (1/1)90%  (129/143)87%  (26/30)
getIndexes (): ArrayList 100% (1/1)100% (2/2)100% (1/1)
getMaxDataModificationId (): long 100% (1/1)100% (2/2)100% (1/1)
getSQL (): String 100% (1/1)100% (4/4)100% (1/1)
getScanIndex (Session): Index 100% (1/1)100% (8/8)100% (1/1)
getTableType (): String 100% (1/1)100% (2/2)100% (1/1)
isBufferResultSetToLocalTemp (): boolean 100% (1/1)100% (4/4)100% (1/1)
isDeterministic (): boolean 100% (1/1)100% (4/4)100% (1/1)
lock (Session, boolean, boolean): boolean 100% (1/1)100% (2/2)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.table;
7 
8import java.sql.ResultSet;
9import java.sql.ResultSetMetaData;
10import java.sql.SQLException;
11import java.util.ArrayList;
12 
13import org.h2.api.ErrorCode;
14import org.h2.engine.Session;
15import org.h2.expression.Expression;
16import org.h2.expression.FunctionCall;
17import org.h2.expression.TableFunction;
18import org.h2.index.FunctionIndex;
19import org.h2.index.Index;
20import org.h2.index.IndexType;
21import org.h2.message.DbException;
22import org.h2.result.LocalResult;
23import org.h2.result.ResultInterface;
24import org.h2.result.Row;
25import org.h2.schema.Schema;
26import org.h2.value.DataType;
27import org.h2.value.Value;
28import org.h2.value.ValueNull;
29import org.h2.value.ValueResultSet;
30 
31/**
32 * A table backed by a system or user-defined function that returns a result
33 * set.
34 */
35public class FunctionTable extends Table {
36 
37    private final FunctionCall function;
38    private final long rowCount;
39    private Expression functionExpr;
40    private LocalResult cachedResult;
41    private Value cachedValue;
42 
43    public FunctionTable(Schema schema, Session session,
44            Expression functionExpr, FunctionCall function) {
45        super(schema, 0, function.getName(), false, true);
46        this.functionExpr = functionExpr;
47        this.function = function;
48        if (function instanceof TableFunction) {
49            rowCount = ((TableFunction) function).getRowCount();
50        } else {
51            rowCount = Long.MAX_VALUE;
52        }
53        function.optimize(session);
54        int type = function.getType();
55        if (type != Value.RESULT_SET) {
56            throw DbException.get(
57                    ErrorCode.FUNCTION_MUST_RETURN_RESULT_SET_1, function.getName());
58        }
59        Expression[] args = function.getArgs();
60        int numParams = args.length;
61        Expression[] columnListArgs = new Expression[numParams];
62        for (int i = 0; i < numParams; i++) {
63            args[i] = args[i].optimize(session);
64            columnListArgs[i] = args[i];
65        }
66        ValueResultSet template = function.getValueForColumnList(
67                session, columnListArgs);
68        if (template == null) {
69            throw DbException.get(
70                    ErrorCode.FUNCTION_MUST_RETURN_RESULT_SET_1, function.getName());
71        }
72        ResultSet rs = template.getResultSet();
73        try {
74            ResultSetMetaData meta = rs.getMetaData();
75            int columnCount = meta.getColumnCount();
76            Column[] cols = new Column[columnCount];
77            for (int i = 0; i < columnCount; i++) {
78                cols[i] = new Column(meta.getColumnName(i + 1),
79                        DataType.getValueTypeFromResultSet(meta, i + 1),
80                        meta.getPrecision(i + 1),
81                        meta.getScale(i + 1), meta.getColumnDisplaySize(i + 1));
82            }
83            setColumns(cols);
84        } catch (SQLException e) {
85            throw DbException.convert(e);
86        }
87    }
88 
89    @Override
90    public boolean lock(Session session, boolean exclusive, boolean forceLockEvenInMvcc) {
91        // nothing to do
92        return false;
93    }
94 
95    @Override
96    public void close(Session session) {
97        // nothing to do
98    }
99 
100    @Override
101    public void unlock(Session s) {
102        // nothing to do
103    }
104 
105    @Override
106    public boolean isLockedExclusively() {
107        return false;
108    }
109 
110    @Override
111    public Index addIndex(Session session, String indexName, int indexId,
112            IndexColumn[] cols, IndexType indexType, boolean create,
113            String indexComment) {
114        throw DbException.getUnsupportedException("ALIAS");
115    }
116 
117    @Override
118    public void removeRow(Session session, Row row) {
119        throw DbException.getUnsupportedException("ALIAS");
120    }
121 
122    @Override
123    public void truncate(Session session) {
124        throw DbException.getUnsupportedException("ALIAS");
125    }
126 
127    @Override
128    public boolean canDrop() {
129        throw DbException.throwInternalError();
130    }
131 
132    @Override
133    public void addRow(Session session, Row row) {
134        throw DbException.getUnsupportedException("ALIAS");
135    }
136 
137    @Override
138    public void checkSupportAlter() {
139        throw DbException.getUnsupportedException("ALIAS");
140    }
141 
142    @Override
143    public String getTableType() {
144        return null;
145    }
146 
147    @Override
148    public Index getScanIndex(Session session) {
149        return new FunctionIndex(this, IndexColumn.wrap(columns));
150    }
151 
152    @Override
153    public ArrayList<Index> getIndexes() {
154        return null;
155    }
156 
157    @Override
158    public boolean canGetRowCount() {
159        return rowCount != Long.MAX_VALUE;
160    }
161 
162    @Override
163    public long getRowCount(Session session) {
164        return rowCount;
165    }
166 
167    @Override
168    public String getCreateSQL() {
169        return null;
170    }
171 
172    @Override
173    public String getDropSQL() {
174        return null;
175    }
176 
177    @Override
178    public void checkRename() {
179        throw DbException.getUnsupportedException("ALIAS");
180    }
181 
182    /**
183     * Read the result from the function. This method buffers the result in a
184     * temporary file.
185     *
186     * @param session the session
187     * @return the result
188     */
189    public ResultInterface getResult(Session session) {
190        ValueResultSet v = getValueResultSet(session);
191        if (v == null) {
192            return null;
193        }
194        if (cachedResult != null && cachedValue == v) {
195            cachedResult.reset();
196            return cachedResult;
197        }
198        LocalResult result = LocalResult.read(session,  v.getResultSet(), 0);
199        if (function.isDeterministic()) {
200            cachedResult = result;
201            cachedValue = v;
202        }
203        return result;
204    }
205 
206    /**
207     * Read the result set from the function. This method doesn't cache.
208     *
209     * @param session the session
210     * @return the result set
211     */
212    public ResultSet getResultSet(Session session) {
213        ValueResultSet v = getValueResultSet(session);
214        return v == null ? null : v.getResultSet();
215    }
216 
217    private ValueResultSet getValueResultSet(Session session) {
218        functionExpr = functionExpr.optimize(session);
219        Value v = functionExpr.getValue(session);
220        if (v == ValueNull.INSTANCE) {
221            return null;
222        }
223        return (ValueResultSet) v;
224    }
225 
226    public boolean isBufferResultSetToLocalTemp() {
227        return function.isBufferResultSetToLocalTemp();
228    }
229 
230    @Override
231    public long getMaxDataModificationId() {
232        // TODO optimization: table-as-a-function currently doesn't know the
233        // last modified date
234        return Long.MAX_VALUE;
235    }
236 
237    @Override
238    public Index getUniqueIndex() {
239        return null;
240    }
241 
242    @Override
243    public String getSQL() {
244        return function.getSQL();
245    }
246 
247    @Override
248    public long getRowCountApproximation() {
249        return rowCount;
250    }
251 
252    @Override
253    public long getDiskSpaceUsed() {
254        return 0;
255    }
256 
257    @Override
258    public boolean isDeterministic() {
259        return function.isDeterministic();
260    }
261 
262    @Override
263    public boolean canReference() {
264        return false;
265    }
266 
267}

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