001: /*
002: * Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
003: * (http://h2database.com/html/license.html).
004: * Initial Developer: H2 Group
005: */
006: package org.h2.table;
007:
008: import java.sql.ResultSet;
009: import java.sql.ResultSetMetaData;
010: import java.sql.SQLException;
011:
012: import org.h2.constant.ErrorCode;
013: import org.h2.engine.Session;
014: import org.h2.expression.Expression;
015: import org.h2.expression.FunctionCall;
016: import org.h2.index.FunctionIndex;
017: import org.h2.index.Index;
018: import org.h2.index.IndexType;
019: import org.h2.message.Message;
020: import org.h2.result.LocalResult;
021: import org.h2.result.Row;
022: import org.h2.schema.Schema;
023: import org.h2.util.ObjectArray;
024: import org.h2.value.DataType;
025: import org.h2.value.Value;
026: import org.h2.value.ValueNull;
027: import org.h2.value.ValueResultSet;
028:
029: /**
030: * A table backed by a system or user defined function that returns a result set.
031: */
032: public class FunctionTable extends Table {
033:
034: private final FunctionCall function;
035:
036: public FunctionTable(Schema schema, Session session,
037: FunctionCall function) throws SQLException {
038: super (schema, 0, function.getName(), false);
039: this .function = function;
040: function.optimize(session);
041: int type = function.getType();
042: if (type != Value.RESULT_SET) {
043: throw Message.getSQLException(
044: ErrorCode.FUNCTION_MUST_RETURN_RESULT_SET_1,
045: function.getName());
046: }
047: int params = function.getParameterCount();
048: Expression[] columnListArgs = new Expression[params];
049: Expression[] args = function.getArgs();
050: for (int i = 0; i < params; i++) {
051: args[i] = args[i].optimize(session);
052: columnListArgs[i] = args[i];
053: }
054: ValueResultSet template = function.getValueForColumnList(
055: session, columnListArgs);
056: if (template == null) {
057: throw Message.getSQLException(
058: ErrorCode.FUNCTION_MUST_RETURN_RESULT_SET_1,
059: function.getName());
060: }
061: ResultSet rs = template.getResultSet();
062: ResultSetMetaData meta = rs.getMetaData();
063: int columnCount = meta.getColumnCount();
064: Column[] cols = new Column[columnCount];
065: for (int i = 0; i < columnCount; i++) {
066: cols[i] = new Column(meta.getColumnName(i + 1), DataType
067: .convertSQLTypeToValueType(meta
068: .getColumnType(i + 1)), meta
069: .getPrecision(i + 1), meta.getScale(i + 1), meta
070: .getColumnDisplaySize(i + 1));
071: }
072: setColumns(cols);
073: }
074:
075: public void lock(Session session, boolean exclusive, boolean force)
076: throws SQLException {
077: }
078:
079: public void close(Session session) throws SQLException {
080: }
081:
082: public void unlock(Session s) {
083: }
084:
085: public boolean isLockedExclusively() {
086: return false;
087: }
088:
089: public Index addIndex(Session session, String indexName,
090: int indexId, IndexColumn[] cols, IndexType indexType,
091: int headPos, String comment) throws SQLException {
092: throw Message.getUnsupportedException();
093: }
094:
095: public void removeRow(Session session, Row row) throws SQLException {
096: throw Message.getUnsupportedException();
097: }
098:
099: public void truncate(Session session) throws SQLException {
100: throw Message.getUnsupportedException();
101: }
102:
103: public boolean canDrop() {
104: throw Message.getInternalError();
105: }
106:
107: public void addRow(Session session, Row row) throws SQLException {
108: throw Message.getUnsupportedException();
109: }
110:
111: public void checkSupportAlter() throws SQLException {
112: throw Message.getUnsupportedException();
113: }
114:
115: public String getTableType() {
116: throw Message.getInternalError();
117: }
118:
119: public Index getScanIndex(Session session) throws SQLException {
120: return new FunctionIndex(this , IndexColumn.wrap(columns),
121: function);
122: }
123:
124: public ObjectArray getIndexes() {
125: return null;
126: }
127:
128: public boolean canGetRowCount() {
129: return false;
130: }
131:
132: public long getRowCount(Session session) throws SQLException {
133: throw Message.getInternalError();
134: }
135:
136: public String getCreateSQL() {
137: return null;
138: }
139:
140: public String getDropSQL() {
141: return null;
142: }
143:
144: public void checkRename() throws SQLException {
145: throw Message.getUnsupportedException();
146: }
147:
148: public LocalResult getResult(Session session) throws SQLException {
149: function.optimize(session);
150: Value v = function.getValue(session);
151: if (v == ValueNull.INSTANCE) {
152: return new LocalResult(0);
153: } else {
154: ValueResultSet value = (ValueResultSet) v;
155: ResultSet rs = value.getResultSet();
156: return LocalResult.read(session, rs, 0);
157: }
158: }
159:
160: public long getMaxDataModificationId() {
161: // TODO optimization: table-as-a-function currently doesn't know the
162: // last modified date
163: return Long.MAX_VALUE;
164: }
165:
166: public Index getUniqueIndex() {
167: return null;
168: }
169:
170: public String getSQL() {
171: return function.getSQL();
172: }
173:
174: }
|