File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\table\FunctionTable.java.html

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