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.expression;
007:
008: import java.sql.SQLException;
009:
010: import org.h2.constant.ErrorCode;
011: import org.h2.engine.Database;
012: import org.h2.engine.Session;
013: import org.h2.message.Message;
014: import org.h2.result.LocalResult;
015: import org.h2.table.Column;
016: import org.h2.tools.SimpleResultSet;
017: import org.h2.util.MathUtils;
018: import org.h2.util.ObjectArray;
019: import org.h2.value.DataType;
020: import org.h2.value.Value;
021: import org.h2.value.ValueArray;
022: import org.h2.value.ValueNull;
023: import org.h2.value.ValueResultSet;
024:
025: /**
026: * Implementation of the functions TABLE(..) and TABLE_DISTINCT(..).
027: */
028: public class TableFunction extends Function implements FunctionCall {
029: private boolean distinct;
030: private Column[] columnList;
031:
032: TableFunction(Database database, FunctionInfo info) {
033: super (database, info);
034: distinct = info.type == Function.TABLE_DISTINCT;
035: }
036:
037: public Value getValue(Session session) throws SQLException {
038: return getTable(session, args, false, distinct);
039: }
040:
041: protected void checkParameterCount(int len) throws SQLException {
042: if (len < 1) {
043: throw Message.getSQLException(
044: ErrorCode.INVALID_PARAMETER_COUNT_2, new String[] {
045: getName(), ">0" });
046: }
047: }
048:
049: public String getSQL() {
050: StringBuffer buff = new StringBuffer();
051: buff.append(getName());
052: buff.append('(');
053: for (int i = 0; i < args.length; i++) {
054: if (i > 0) {
055: buff.append(", ");
056: }
057: buff.append(columnList[i].getCreateSQL());
058: buff.append("=");
059: Expression e = args[i];
060: buff.append(e.getSQL());
061: }
062: buff.append(')');
063: return buff.toString();
064: }
065:
066: public String getName() {
067: return distinct ? "TABLE_DISTINCT" : "TABLE";
068: }
069:
070: public int getRowCount(Session session) throws SQLException {
071: int len = columnList.length;
072: int rowCount = 0;
073: for (int i = 0; i < len; i++) {
074: Expression expr = args[i];
075: if (expr.isConstant()) {
076: Value v = expr.getValue(session);
077: if (v != ValueNull.INSTANCE) {
078: ValueArray array = (ValueArray) v
079: .convertTo(Value.ARRAY);
080: Value[] l = array.getList();
081: rowCount = Math.max(rowCount, l.length);
082: }
083: }
084: }
085: return rowCount;
086: }
087:
088: public ValueResultSet getValueForColumnList(Session session,
089: Expression[] nullArgs) throws SQLException {
090: return getTable(session, args, true, false);
091: }
092:
093: public void setColumns(ObjectArray columns) {
094: this .columnList = new Column[columns.size()];
095: columns.toArray(columnList);
096: }
097:
098: private ValueResultSet getTable(Session session, Expression[] args,
099: boolean onlyColumnList, boolean distinct)
100: throws SQLException {
101: int len = columnList.length;
102: Expression[] header = new Expression[len];
103: Database db = session.getDatabase();
104: for (int i = 0; i < len; i++) {
105: Column c = columnList[i];
106: ExpressionColumn col = new ExpressionColumn(db, c);
107: header[i] = col;
108: }
109: LocalResult result = new LocalResult(session, header, len);
110: if (distinct) {
111: result.setDistinct();
112: }
113: if (!onlyColumnList) {
114: Value[][] list = new Value[len][];
115: int rowCount = 0;
116: for (int i = 0; i < len; i++) {
117: Value v = args[i].getValue(session);
118: if (v == ValueNull.INSTANCE) {
119: list[i] = new Value[0];
120: } else {
121: ValueArray array = (ValueArray) v
122: .convertTo(Value.ARRAY);
123: Value[] l = array.getList();
124: list[i] = l;
125: rowCount = Math.max(rowCount, l.length);
126: }
127: }
128: for (int row = 0; row < rowCount; row++) {
129: Value[] r = new Value[len];
130: for (int j = 0; j < len; j++) {
131: Value[] l = list[j];
132: Value v;
133: if (l.length <= row) {
134: v = ValueNull.INSTANCE;
135: } else {
136: Column c = columnList[j];
137: v = l[row];
138: v = v.convertTo(c.getType());
139: v = v.convertPrecision(c.getPrecision());
140: v = v.convertScale(true, c.getScale());
141: }
142: r[j] = v;
143: }
144: result.addRow(r);
145: }
146: }
147: result.done();
148: ValueResultSet vr = ValueResultSet.get(getSimpleResultSet(
149: result, Integer.MAX_VALUE));
150: return vr;
151: }
152:
153: SimpleResultSet getSimpleResultSet(LocalResult rs, int maxrows)
154: throws SQLException {
155: int columnCount = rs.getVisibleColumnCount();
156: SimpleResultSet simple = new SimpleResultSet();
157: for (int i = 0; i < columnCount; i++) {
158: String name = rs.getColumnName(i);
159: int sqlType = DataType.convertTypeToSQLType(rs
160: .getColumnType(i));
161: int precision = MathUtils.convertLongToInt(rs
162: .getColumnPrecision(i));
163: int scale = rs.getColumnScale(i);
164: simple.addColumn(name, sqlType, precision, scale);
165: }
166: rs.reset();
167: for (int i = 0; i < maxrows && rs.next(); i++) {
168: Object[] list = new Object[columnCount];
169: for (int j = 0; j < columnCount; j++) {
170: list[j] = rs.currentRow()[j].getObject();
171: }
172: simple.addRow(list);
173: }
174: return simple;
175: }
176:
177: }
|