package org.postgresforest.vm.jdbc;

import java.sql.Array;
import java.sql.Date;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.Map;
import java.util.Vector;

import org.postgresforest.core.BaseStatement;
import org.postgresforest.core.Field;
import org.postgresforest.core.Query;
import org.postgresforest.core.ResultCursor;
import org.postgresforest.jdbc3.Jdbc3Array;
import org.postgresforest.jdbc3.Jdbc3Blob;
import org.postgresforest.jdbc3.Jdbc3Clob;

public class ForestResultSet extends org.postgresforest.jdbc3.AbstractJdbc3ResultSet implements java.sql.ResultSet
{
	ForestResultSet(Query originalQuery, BaseStatement statement, Field[] fields, Vector tuples, ResultCursor cursor,
                   int maxRows, int maxFieldSize, int rsType, int rsConcurrency, int rsHoldability) throws SQLException
    {
        super(originalQuery, statement, fields, tuples, cursor, maxRows, maxFieldSize, rsType, rsConcurrency, rsHoldability);
    }

    public java.sql.ResultSetMetaData getMetaData() throws SQLException
    {
        checkClosed();
        return new ForestResultSetMetaData(connection, fields);
    }

    public java.sql.Clob getClob(int i) throws SQLException
    {
        checkResultSet(i);
        wasNullFlag = (this_row[i - 1] == null);
        if (wasNullFlag)
            return null;

        return new Jdbc3Clob(connection, getInt(i));
    }

    public java.sql.Blob getBlob(int i) throws SQLException
    {
        checkResultSet(i);
        wasNullFlag = (this_row[i - 1] == null);
        if (wasNullFlag)
            return null;

        return new Jdbc3Blob(connection, getInt(i));
    }

    public Array createArray(int i) throws SQLException
    {
        checkResultSet(i);
        return new Jdbc3Array(connection, i, fields[i - 1], this);
    }

    public Object getObject(String s, Map map) throws SQLException
    {
        return getObjectImpl(s, map);
    }

    public Object getObject(int i, Map map) throws SQLException
    {
        return getObjectImpl(i, map);
    }
    

    
    
    public Vector getRows(){
    	return rows; 
    } 
    
    public void setRows(Vector r){
    	rows = r;
    	current_row = -1;
    } 

	/**
	 * 指定されたステートメントで、複製クラスを作成する
	 * @param statement - 複製するResultSetにセットするステートメント
	 * @return 複製された ResultSet
	 */
	public ForestResultSet Copy( )throws SQLException
	{
		return new ForestResultSet(originalQuery,statement,fields,rows,cursor,maxRows,maxFieldSize,getType(),getConcurrency(),statement.getResultSetHoldability());
	}
    
    /**s
	 * 結果更新
	 * カラム（INDEX）を指定して値を更新する
	 *  
	 * @param columnIndex カラムINDEX
	 * @param valueObject 更新値
	 * @throws SQLException
	 * @since 2.0
	 */
	public synchronized void setObject(int columnIndex, Object valueObject)
	throws SQLException
	{

		
        switch ( getSQLType(columnIndex ) )
        {

        case Types.DECIMAL:
        case Types.BIGINT:
        case Types.DOUBLE:
        case Types.BIT:
        case Types.VARCHAR:
        case Types.SMALLINT:
        case Types.FLOAT:
        case Types.INTEGER:
        case Types.CHAR:
        case Types.NUMERIC:
        case Types.REAL:
        case Types.TINYINT:
        case Types.OTHER:
        	this_row[columnIndex-1] = connection.encodeString(String.valueOf( valueObject));
            break;

        //
        // toString() isn't enough for date and time types; we must format it correctly
        // or we won't be able to re-parse it.
        //

        case Types.DATE:
        	this_row[columnIndex-1] =
                connection.encodeString(connection.getTimestampUtils().toString(null, (Date)valueObject));
            break;

        case Types.TIME:
        	this_row[columnIndex-1] =
                connection.encodeString(connection.getTimestampUtils().toString(null, (Time)valueObject));
            break;

        case Types.TIMESTAMP:
        	this_row[columnIndex-1] =
                connection.encodeString(connection.getTimestampUtils().toString(null, (Timestamp)valueObject));
            break;

        case Types.NULL:
            // Should never happen?
            break;

        default:
        	this_row[columnIndex-1] = (byte[]) valueObject;
        }
		

	}

	//集約関数で値の操作をするときに  ResultSet.TYPE_FORWARD_ONLYのためcheckScrollable(); でエラーとなるので、
	//checkScrollable()をスルー
	public void _beforeFirst() throws SQLException
    {

        if (rows.size() > 0)
            current_row = -1;

        onInsertRow = false;
        this_row = null;
        rowBuffer = null;
    }

	//集約関数で値の操作をするときに  ResultSet.TYPE_FORWARD_ONLYのためcheckScrollable(); でエラーとなるので、
	//checkScrollable()をスルー
	public boolean _last() throws SQLException
    {

        final int rows_size = rows.size();
        if (rows_size <= 0)
            return false;

        current_row = rows_size - 1;
        this_row = (byte[][]) rows.elementAt(current_row);

        rowBuffer = new byte[this_row.length][];
        System.arraycopy(this_row, 0, rowBuffer, 0, this_row.length);
        onInsertRow = false;

        return true;
    }

}

