/* * Copyright 2014-2015 the original author or authors * * Licensed under the Apache License, Version 2.0 (the “License”); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an “AS IS” BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.wplatform.ddal.command.expression; import java.util.ArrayList; import com.wplatform.ddal.dbobject.table.Column; import com.wplatform.ddal.engine.Database; import com.wplatform.ddal.engine.Session; import com.wplatform.ddal.message.DbException; import com.wplatform.ddal.message.ErrorCode; import com.wplatform.ddal.result.LocalResult; import com.wplatform.ddal.result.ResultInterface; import com.wplatform.ddal.result.SimpleResultSet; import com.wplatform.ddal.util.MathUtils; import com.wplatform.ddal.util.StatementBuilder; import com.wplatform.ddal.value.*; /** * Implementation of the functions TABLE(..) and TABLE_DISTINCT(..). */ public class TableFunction extends Function { private final boolean distinct; private final long rowCount; private Column[] columnList; TableFunction(Database database, FunctionInfo info, long rowCount) { super(database, info); distinct = info.type == Function.TABLE_DISTINCT; this.rowCount = rowCount; } private static SimpleResultSet getSimpleResultSet(ResultInterface rs, int maxrows) { int columnCount = rs.getVisibleColumnCount(); SimpleResultSet simple = new SimpleResultSet(); simple.setAutoClose(false); for (int i = 0; i < columnCount; i++) { String name = rs.getColumnName(i); int sqlType = DataType.convertTypeToSQLType(rs.getColumnType(i)); int precision = MathUtils.convertLongToInt(rs.getColumnPrecision(i)); int scale = rs.getColumnScale(i); simple.addColumn(name, sqlType, precision, scale); } rs.reset(); for (int i = 0; i < maxrows && rs.next(); i++) { Object[] list = new Object[columnCount]; for (int j = 0; j < columnCount; j++) { list[j] = rs.currentRow()[j].getObject(); } simple.addRow(list); } return simple; } @Override public Value getValue(Session session) { return getTable(session, args, false, distinct); } @Override protected void checkParameterCount(int len) { if (len < 1) { throw DbException.get(ErrorCode.INVALID_PARAMETER_COUNT_2, getName(), ">0"); } } @Override public String getSQL() { StatementBuilder buff = new StatementBuilder(getName()); buff.append('('); int i = 0; for (Expression e : args) { buff.appendExceptFirst(", "); buff.append(columnList[i++].getCreateSQL()).append('=').append(e.getSQL()); } return buff.append(')').toString(); } @Override public String getName() { return distinct ? "TABLE_DISTINCT" : "TABLE"; } @Override public ValueResultSet getValueForColumnList(Session session, Expression[] nullArgs) { return getTable(session, args, true, false); } public void setColumns(ArrayList<Column> columns) { this.columnList = new Column[columns.size()]; columns.toArray(columnList); } private ValueResultSet getTable(Session session, Expression[] argList, boolean onlyColumnList, boolean distinctRows) { int len = columnList.length; Expression[] header = new Expression[len]; Database db = session.getDatabase(); for (int i = 0; i < len; i++) { Column c = columnList[i]; ExpressionColumn col = new ExpressionColumn(db, c); header[i] = col; } LocalResult result = new LocalResult(session, header, len); if (distinctRows) { result.setDistinct(); } if (!onlyColumnList) { Value[][] list = new Value[len][]; int rows = 0; for (int i = 0; i < len; i++) { Value v = argList[i].getValue(session); if (v == ValueNull.INSTANCE) { list[i] = new Value[0]; } else { ValueArray array = (ValueArray) v.convertTo(Value.ARRAY); Value[] l = array.getList(); list[i] = l; rows = Math.max(rows, l.length); } } for (int row = 0; row < rows; row++) { Value[] r = new Value[len]; for (int j = 0; j < len; j++) { Value[] l = list[j]; Value v; if (l.length <= row) { v = ValueNull.INSTANCE; } else { Column c = columnList[j]; v = l[row]; v = c.convert(v); v = v.convertPrecision(c.getPrecision(), false); v = v.convertScale(true, c.getScale()); } r[j] = v; } result.addRow(r); } } result.done(); ValueResultSet vr = ValueResultSet.get(getSimpleResultSet(result, Integer.MAX_VALUE)); return vr; } public long getRowCount() { return rowCount; } @Override public Expression[] getExpressionColumns(Session session) { return getExpressionColumns(session, getTable(session, getArgs(), true, false).getResultSet()); } }