package org.maachang.mimdb.jdbc ;

import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.net.URL;
import java.sql.Array;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Date;
import java.sql.NClob;
import java.sql.ParameterMetaData;
import java.sql.Ref;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.RowId;
import java.sql.SQLException;
import java.sql.SQLXML;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Calendar;

import org.maachang.mimdb.core.MimdbConnection;
import org.maachang.mimdb.core.MimdbPreparedStatement;
import org.maachang.mimdb.core.MimdbResult;


/**
 * Mimdb-JDBC プリコンパイル済みStatement.
 * 
 * @version 2013/11/19
 * @author masahito suzuki
 * @since MasterInMemDB 1.00
 */
public class MimdbJdbcPreparedStatement extends MimdbJdbcStatement implements java.sql.PreparedStatement {
    protected String name ;
    protected MimdbPreparedStatement prepared = null ;
    
    protected MimdbJdbcPreparedStatement() {}
    
    protected MimdbJdbcPreparedStatement( MimdbJdbcConnection c,MimdbConnection cc,String sql )
        throws SQLException {
        super( c,cc ) ;
        MimdbPreparedStatement ps = null ;
        try {
            ps = cc.getPreparedStatement( sql ) ;
        } catch( RuntimeException r ) {
            close() ;
            throw r ;
        } catch( Exception e ) {
            close() ;
            throw new SQLException( e ) ;
        }
        prepared = ps ;
    }
    
    protected void finalize() throws Exception {
        close() ;
    }
    
    public void close() throws SQLException {
        super.close() ;
        if( prepared != null ) {
            prepared.close() ;
            prepared = null ;
        }
    }
    
    public void addBatch() throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void clearParameters() throws SQLException {
        check() ;
    }
    public boolean execute() throws SQLException {
        errorsql( "サポートされていません" ) ;
        return false ;
    }
    public ResultSet executeQuery() throws SQLException {
        check() ;
        try {
            prepared.setFetchSize( fetchSize ) ;
            if( maxRows >= 0 ) {
                prepared.setLimit( maxRows ) ;
                maxRows = -1 ;
            }
            MimdbResult res = prepared.executeQuery() ;
            nowResult = new MimdbJdbcResultSet( this,res ) ;
            return nowResult ;
        } catch( Exception e ) {
            errorsql( e ) ;
        }
        return null ;
    }
    public int executeUpdate() throws SQLException {
        errorsql( "サポートされていません" ) ;
        return -1 ;
    }
    public ResultSetMetaData getMetaData() throws SQLException {
        check() ;
        if( nowResult == null || nowResult.isClosed() ) {
            return null ;
        }
        return new MimdbJdbcResultSetMetaData( nowResult.result ) ;
    }
    public ParameterMetaData getParameterMetaData() throws SQLException {
        check() ;
        return new MimdbJdbcParameterMetaData( prepared ) ;
    }
    
    
    public void setArray(int parameterIndex, Array x) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void setBlob(int parameterIndex, Blob x) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void setBytes(int parameterIndex, byte[] x) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void setClob(int parameterIndex, Clob x) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void setClob(int parameterIndex, Reader reader) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void setClob(int parameterIndex, Reader reader, long length) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void setNClob(int parameterIndex, NClob value) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void setNClob(int parameterIndex, Reader reader) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void setRef(int parameterIndex, Ref x) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void setRowId(int parameterIndex, RowId x) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void setShort(int parameterIndex, short x) throws SQLException {
        check() ;
        prepared.setParams( parameterIndex-1,x ) ;
    }
    public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException {
        errorsql( "サポートされていません" ) ;
    }
    
    
    public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException {
        check() ;
        if( x == null ) {
            prepared.setParams( parameterIndex-1,null ) ;
        }
        else {
            prepared.setParams( parameterIndex-1,x.toString() ) ;
        }
    }
    public void setBoolean(int parameterIndex, boolean x) throws SQLException {
        check() ;
        prepared.setParams( parameterIndex-1,x ) ;
    }
    public void setByte(int parameterIndex, byte x) throws SQLException {
        check() ;
        prepared.setParams( parameterIndex-1,x ) ;
    }
    public void setDate(int parameterIndex, Date x) throws SQLException {
        check() ;
        if( x == null ) {
            prepared.setParams( parameterIndex-1,null ) ;
        }
        else {
            prepared.setParams( parameterIndex-1,x ) ;
        }
    }
    public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException {
        check() ;
        if( x == null ) {
            prepared.setParams( parameterIndex-1,null ) ;
        }
        else {
            if( cal != null ) {
                cal.setTime( x ) ;
                x = new Date( cal.getTime().getTime() ) ;
            }
            prepared.setParams( parameterIndex-1,x ) ;
        }
    }
    public void setDouble(int parameterIndex, double x) throws SQLException {
        check() ;
        prepared.setParams( parameterIndex-1,x ) ;
    }
    public void setFloat(int parameterIndex, float x) throws SQLException {
        check() ;
        prepared.setParams( parameterIndex-1,x ) ;
    }
    public void setInt(int parameterIndex, int x) throws SQLException {
        check() ;
        prepared.setParams( parameterIndex-1,x ) ;
    }
    public void setLong(int parameterIndex, long x) throws SQLException {
        check() ;
        prepared.setParams( parameterIndex-1,x ) ;
    }
    public void setNString(int parameterIndex, String value) throws SQLException {
        check() ;
        if( value == null ) {
            prepared.setParams( parameterIndex-1,null ) ;
        }
        else {
            prepared.setParams( parameterIndex-1,value ) ;
        }
    }
    public void setNull(int parameterIndex, int sqlType) throws SQLException {
        check() ;
        prepared.setParams( parameterIndex-1,null ) ;
    }
    public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException {
        check() ;
        prepared.setParams( parameterIndex-1,null ) ;
    }
    public void setObject(int parameterIndex, Object x) throws SQLException {
        check() ;
        if( x == null ) {
            prepared.setParams( parameterIndex-1,null ) ;
        }
        else {
            prepared.setParams( parameterIndex-1,x ) ;
        }
    }
    public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {
        check() ;
        if( x == null ) {
            prepared.setParams( parameterIndex-1,null ) ;
        }
        else {
            prepared.setParams( parameterIndex-1,x ) ;
        }
    }
    public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException {
        check() ;
        if( x == null ) {
            prepared.setParams( parameterIndex-1,null ) ;
        }
        else {
            prepared.setParams( parameterIndex-1,x ) ;
        }
    }
    public void setString(int parameterIndex, String x) throws SQLException {
        check() ;
        if( x == null ) {
            prepared.setParams( parameterIndex-1,null ) ;
        }
        else {
            prepared.setParams( parameterIndex-1,x ) ;
        }
    }
    public void setTime(int parameterIndex, Time x) throws SQLException {
        check() ;
        if( x == null ) {
            prepared.setParams( parameterIndex-1,null ) ;
        }
        else {
            prepared.setParams( parameterIndex-1,x ) ;
        }
    }
    public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException {
        check() ;
        if( x == null ) {
            prepared.setParams( parameterIndex-1,null ) ;
        }
        else {
            prepared.setParams( parameterIndex-1,x ) ;
        }
    }
    public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException {
        check() ;
        if( x == null ) {
            prepared.setParams( parameterIndex-1,null ) ;
        }
        else {
            prepared.setParams( parameterIndex-1,x ) ;
        }
    }
    public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException {
        check() ;
        if( x == null ) {
            prepared.setParams( parameterIndex-1,null ) ;
        }
        else {
            prepared.setParams( parameterIndex-1,x ) ;
        }
    }
    public void setURL(int parameterIndex, URL x) throws SQLException {
        check() ;
        if( x == null ) {
            prepared.setParams( parameterIndex-1,null ) ;
        }
        else {
            prepared.setParams( parameterIndex-1,x.toString() ) ;
        }
    }
    
    // エラーメッセージ出力.
    private final void errorsql( String msg ) throws SQLException {
        throw new SQLException( "エラー:" + name + " " + msg ) ;
    }
    // エラーメッセージ出力.
    private final void errorsql( Exception e ) throws SQLException {
        throw new SQLException( "エラー:" + name,e ) ;
    }
}
