Package org.lealone.dbobject.table

Source Code of org.lealone.dbobject.table.FunctionTable

/*
* Copyright 2004-2013 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.lealone.dbobject.table;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;

import org.lealone.constant.ErrorCode;
import org.lealone.dbobject.Schema;
import org.lealone.dbobject.index.FunctionIndex;
import org.lealone.dbobject.index.Index;
import org.lealone.dbobject.index.IndexType;
import org.lealone.engine.Session;
import org.lealone.expression.Expression;
import org.lealone.expression.FunctionCall;
import org.lealone.expression.TableFunction;
import org.lealone.message.DbException;
import org.lealone.result.LocalResult;
import org.lealone.result.ResultInterface;
import org.lealone.result.Row;
import org.lealone.value.DataType;
import org.lealone.value.Value;
import org.lealone.value.ValueNull;
import org.lealone.value.ValueResultSet;

/**
* A table backed by a system or user-defined function that returns a result set.
*/
public class FunctionTable extends Table {

    private final FunctionCall function;
    private final long rowCount;
    private Expression functionExpr;
    private LocalResult cachedResult;
    private Value cachedValue;

    public FunctionTable(Schema schema, Session session, Expression functionExpr, FunctionCall function) {
        super(schema, 0, function.getName(), false, true);
        this.functionExpr = functionExpr;
        this.function = function;
        if (function instanceof TableFunction) {
            rowCount = ((TableFunction) function).getRowCount();
        } else {
            rowCount = Long.MAX_VALUE;
        }
        function.optimize(session);
        int type = function.getType();
        if (type != Value.RESULT_SET) {
            throw DbException.get(ErrorCode.FUNCTION_MUST_RETURN_RESULT_SET_1, function.getName());
        }
        int params = function.getParameterCount();
        Expression[] columnListArgs = new Expression[params];
        Expression[] args = function.getArgs();
        for (int i = 0; i < params; i++) {
            args[i] = args[i].optimize(session);
            columnListArgs[i] = args[i];
        }
        ValueResultSet template = function.getValueForColumnList(session, columnListArgs);
        if (template == null) {
            throw DbException.get(ErrorCode.FUNCTION_MUST_RETURN_RESULT_SET_1, function.getName());
        }
        ResultSet rs = template.getResultSet();
        try {
            ResultSetMetaData meta = rs.getMetaData();
            int columnCount = meta.getColumnCount();
            Column[] cols = new Column[columnCount];
            for (int i = 0; i < columnCount; i++) {
                cols[i] = new Column(meta.getColumnName(i + 1), DataType.convertSQLTypeToValueType(meta.getColumnType(i + 1)),
                        meta.getPrecision(i + 1), meta.getScale(i + 1), meta.getColumnDisplaySize(i + 1));
            }
            setColumns(cols);
        } catch (SQLException e) {
            throw DbException.convert(e);
        }
    }

    public void lock(Session session, boolean exclusive, boolean force) {
        // nothing to do
    }

    public void close(Session session) {
        // nothing to do
    }

    public void unlock(Session s) {
        // nothing to do
    }

    public boolean isLockedExclusively() {
        return false;
    }

    public Index addIndex(Session session, String indexName, int indexId, IndexColumn[] cols, IndexType indexType,
            boolean create, String indexComment) {
        throw DbException.getUnsupportedException("ALIAS");
    }

    public void removeRow(Session session, Row row) {
        throw DbException.getUnsupportedException("ALIAS");
    }

    public void truncate(Session session) {
        throw DbException.getUnsupportedException("ALIAS");
    }

    public boolean canDrop() {
        throw DbException.throwInternalError();
    }

    public void addRow(Session session, Row row) {
        throw DbException.getUnsupportedException("ALIAS");
    }

    public void checkSupportAlter() {
        throw DbException.getUnsupportedException("ALIAS");
    }

    public String getTableType() {
        return null;
    }

    public Index getScanIndex(Session session) {
        return new FunctionIndex(this, IndexColumn.wrap(columns));
    }

    public ArrayList<Index> getIndexes() {
        return null;
    }

    public boolean canGetRowCount() {
        return rowCount != Long.MAX_VALUE;
    }

    public long getRowCount(Session session) {
        return rowCount;
    }

    public String getCreateSQL() {
        return null;
    }

    public String getDropSQL() {
        return null;
    }

    public void checkRename() {
        throw DbException.getUnsupportedException("ALIAS");
    }

    /**
     * Read the result from the function. This method caches the result.
     *
     * @param session the session
     * @return the result
     */
    public ResultInterface getResult(Session session) {
        ValueResultSet v = getValueResultSet(session);
        if (v == null) {
            return null;
        }
        if (cachedResult != null && cachedValue == v) {
            cachedResult.reset();
            return cachedResult;
        }
        LocalResult result = LocalResult.read(session, v.getResultSet(), 0);
        if (function.isDeterministic()) {
            cachedResult = result;
            cachedValue = v;
        }
        return result;
    }

    /**
     * Read the result set from the function. This method doesn't cache.
     *
     * @param session the session
     * @return the result set
     */
    public ResultSet getResultSet(Session session) {
        ValueResultSet v = getValueResultSet(session);
        return v == null ? null : v.getResultSet();
    }

    private ValueResultSet getValueResultSet(Session session) {
        functionExpr = functionExpr.optimize(session);
        Value v = functionExpr.getValue(session);
        if (v == ValueNull.INSTANCE) {
            return null;
        }
        return (ValueResultSet) v;
    }

    public boolean isFast() {
        return function.isFast();
    }

    public long getMaxDataModificationId() {
        // TODO optimization: table-as-a-function currently doesn't know the
        // last modified date
        return Long.MAX_VALUE;
    }

    public Index getUniqueIndex() {
        return null;
    }

    public String getSQL() {
        return function.getSQL();
    }

    public long getRowCountApproximation() {
        return rowCount;
    }

    public long getDiskSpaceUsed() {
        return 0;
    }

    public boolean isDeterministic() {
        return function.isDeterministic();
    }

    public boolean canReference() {
        return false;
    }

}
TOP

Related Classes of org.lealone.dbobject.table.FunctionTable

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.