/*
* 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());
}
}