/*
_____       _    _    Corso   Italia,  178
(_|__   .  (_   |_|_  56125           Pisa
(_|_) |)|(()_)()| |   tel.  +39  050 46380
  |   |               picosoft@picosoft.it

 Copyright (C) Picosoft s.r.l. 1995-2002

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2, or (at your option)
 any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/
package IT.picosoft.jdbc;

import java.math.BigDecimal;
import java.sql.*;
import java.util.Hashtable;

public class PicoStatement /*extends PicoObject */ implements Statement {

   protected PicoDbApi odbcApi;
   protected OdbcStatement hStmt;
   protected SQLWarning lastWarning;
   // protected Hashtable typeInfo;
   protected ResultSet myResultSet;
   protected PicoConnection myConnection;

   public PicoStatement(PicoConnection con, PicoDbApi api/*, Hashtable info*/)
                               throws SQLException {
      lastWarning = null;
      myConnection = con;
      odbcApi = api;
      hStmt = new OdbcStatement (odbcApi, myConnection.getHDBC());
      // typeInfo = info;
   }

   OdbcStatement getHSTMT() {
      return hStmt;
   }

   public void addBatch(String s) throws SQLException {
      throw new UnsupportedOperationException();
   }

   public void cancel() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*Statement.cancel");
      clearWarnings();
      try {
         odbcApi.SQLCancel(hStmt);
      } catch(SQLWarning sqlwarning) {
         setWarning(sqlwarning);
      }
   }

   public void clearBatch() throws SQLException {
      throw new UnsupportedOperationException();
   }

   protected synchronized void clearMyResultSet() throws SQLException {
      if(myResultSet != null) {
         myResultSet.close();
         myResultSet = null;
      }
   }

   public void clearWarnings() throws SQLException {
      lastWarning = null;
   }

   public synchronized void close() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*Statement.close hStmt=" + hStmt + 
                                ", rs=" + myResultSet +
                                ", this=" + this);
      if (!myConnection.isClosed()) {
         clearMyResultSet();
         try {
            clearWarnings();
            if (!hStmt.isDropped()) {
               hStmt.drop();
            }
         } catch(SQLException ex) { }
      }
      myConnection.deregisterStatement(this);
   }

   public synchronized boolean execute(String s) throws SQLException {
      boolean Return = false;
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*Statement.execute (" + s + ")");
      clearWarnings();
      reset();
      lockIfNecessary(s);
      try {
         odbcApi.SQLExecDirect(hStmt, s);
      } catch(SQLWarning sqlwarning) {
         setWarning (sqlwarning);
      }
      int nCol = -1;
      if((nCol = getColumnCount()) > 0)
         Return = true;
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*Statement.execute nCol=" + nCol);
      return Return;
   }

   public boolean execute(String s, int autoGeneratedKeys) throws SQLException {
      throw new UnsupportedOperationException();
   }

   public boolean execute(String s, int columnIndexes[]) throws SQLException {
      throw new UnsupportedOperationException();
   }

   public boolean execute(String s, String columnIndexes[]) throws SQLException{
      throw new UnsupportedOperationException();
   }

   public int[] executeBatch() throws SQLException {
      throw new UnsupportedOperationException();
   }

   public ResultSet executeQuery(String s) throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*Statement.executeQuery (" + s + ")");
      ResultSet resultset = null;
      if(execute(s))
         resultset = getResultSet(false);
      else
         throw new SQLException("No ResultSet was produced");
      return resultset;
   }

   public int executeUpdate(String s) throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*Statement.executeUpdate (" + s + ")");
      int i = -1;
      if(!execute(s))
         i = getUpdateCount();
      else
         throw new SQLException("No row count was produced");
      return i;
   }

   public int executeUpdate(String s, int autoGeneratedKeys)
                                                 throws SQLException {
      throw new UnsupportedOperationException();
   }

   public int executeUpdate(String s, int columnIndexes[])
                                                 throws SQLException {
      throw new UnsupportedOperationException();
   }

   public int executeUpdate(String s, String columnIndexes[])
                                                 throws SQLException {
      throw new UnsupportedOperationException();
   }
 
   protected void finalize() {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("Statement.finalize " + this);
      try {
         close();
      } catch(SQLException ex) { }
   }

   protected int getColumnCount() throws SQLException {
      int i = 0;
      try {
         i = odbcApi.SQLNumResultCols(hStmt);
      } catch(PicoSQLWarning jdbcodbcsqlwarning) {
         BigDecimal bigdecimal = (BigDecimal)jdbcodbcsqlwarning.value;
         i = bigdecimal.intValue();
      }
      return i;
   }

   public Connection getConnection() throws SQLException {
      throw new UnsupportedOperationException();
   }

   public int getFetchDirection() throws SQLException {
      throw new UnsupportedOperationException();
   }

   public int getFetchSize() throws SQLException {
      throw new UnsupportedOperationException();
   }

   public int getMaxFieldSize() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*Statement.getMaxFieldSize");
      return getStmtOption(OdbcDef.SQL_MAX_LENGTH);
   }

   public int getMaxRows() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*Statement.getMaxRows");
      return getStmtOption(OdbcDef.SQL_MAX_ROWS);
   }

   public boolean getMoreResults() throws SQLException {
      return false;
   }

   public boolean getMoreResults(int current) throws SQLException {
      return false;
   }

/*
   protected int getPrecision(int i) {
      int j = -1;
      if(typeInfo != null) {
         PicoTypeInfo picotypeinfo = (PicoTypeInfo)typeInfo.get(new Integer(i));
         if(picotypeinfo != null)
            j = picotypeinfo.getPrec();
      }
      return j;
   }
*/

   public int getQueryTimeout() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*Statement.getQueryTimeout");
      return getStmtOption(OdbcDef.SQL_QUERY_TIMEOUT);
   }

   public ResultSet getResultSet() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*Statement.getResultSet");
      myResultSet = getResultSet(true);
      return myResultSet;
   }

   protected ResultSet getResultSet(boolean flag) throws SQLException {
      if(myResultSet != null)
         throw new SQLException("Invalid state for getResultSet");
      PicoResultSet rs = null;
      int i = 1;
      if(flag)
         i = getColumnCount();
      if(i > 0) {
         /* 23 10 00 
         rs = new PicoResultSet(odbcApi, this);
         */
         myResultSet = new PicoResultSet(odbcApi, this);
      } else {
         clearMyResultSet();
      }
      /* 23 10 00 
      return rs;
      */
      return myResultSet;
   }

   public int getResultSetConcurrency() throws SQLException {
      throw new UnsupportedOperationException();
   }

   public int getResultSetType() {
      throw new UnsupportedOperationException();
   }

   public int getResultSetHoldability() {
      throw new UnsupportedOperationException();
   }

   protected int getRowCount() throws SQLException {
      int i = 0;
      try {
         i = odbcApi.SQLRowCount(hStmt);
      } catch(PicoSQLWarning jdbcodbcsqlwarning) {
         BigDecimal bigdecimal = (BigDecimal)jdbcodbcsqlwarning.value;
         i = bigdecimal.intValue();
      }
      return i;
   }

   protected int getStmtOption(short word0) throws SQLException {
      int i = 0;
      clearWarnings();
      try {
         i = odbcApi.SQLGetStmtOption(hStmt, word0);
      } catch(PicoSQLWarning jdbcodbcsqlwarning) {
         BigDecimal bigdecimal = (BigDecimal)jdbcodbcsqlwarning.value;
         i = bigdecimal.intValue();
         setWarning(PicoDbApi.convertWarning(jdbcodbcsqlwarning));
      }
      return i;
   }

   public int getUpdateCount() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*Statement.getUpdateCount");
      int i = -1;
      if(getColumnCount() == 0)
         i = getRowCount();
      return i;
   }

   public SQLWarning getWarnings() throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*Statement.getWarnings");
      return lastWarning;
   }


   protected boolean lockIfNecessary(String s) throws SQLException {
      boolean flag = false;
      String s1 = s.toUpperCase();
      int i = s1.indexOf(" FOR UPDATE");
      if(i > 0) {
         if(DriverManager.getLogWriter() != null)
            DriverManager.println("Setting concurrency for update");
         try {
            odbcApi.SQLSetStmtOption(hStmt, OdbcDef.SQL_CONCURRENCY, 
                                            OdbcDef.SQL_CONCUR_LOCK);
         } catch(SQLWarning sqlwarning) {
            setWarning(sqlwarning);
         }
         flag = true;
      }
      return flag;
   }

   protected void reset() throws SQLException {
      clearWarnings();
      if(myResultSet != null)
         clearMyResultSet();
      else
         hStmt.close();
   }

   public void setCursorName(String s) throws SQLException {
      throw new UnsupportedOperationException();
   }

   public void setEscapeProcessing(boolean flag) throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*Statement.setEscapeProcessing (" + flag + ")");
      int i = 0;
      if(!flag)
         i = 1;
      odbcApi.SQLSetStmtOption(hStmt, OdbcDef.SQL_NOSCAN, i);
   }

   public void setFetchDirection(int i) throws SQLException {
      throw new UnsupportedOperationException();
   }

   public void setFetchSize(int i) throws SQLException {
      throw new UnsupportedOperationException();
   }

   public void setMaxFieldSize(int i) throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*Statement.setMaxFieldSize (" + i + ")");
      odbcApi.SQLSetStmtOption(hStmt, OdbcDef.SQL_MAX_LENGTH, i);
   }

   public void setMaxRows(int i)
      throws SQLException
   {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*Statement.setMaxRows (" + i + ")");
      odbcApi.SQLSetStmtOption(hStmt, OdbcDef.SQL_MAX_ROWS, i);
   }

   public void setQueryTimeout(int i) throws SQLException {
      if(DriverManager.getLogWriter() != null)
         DriverManager.println("*Statement.setQueryTimeout (" + i + ")");
      odbcApi.SQLSetStmtOption(hStmt, OdbcDef.SQL_QUERY_TIMEOUT, i);
   }

   public void setWarning(SQLWarning sqlwarning) throws SQLException {
      lastWarning = sqlwarning;
   }

   public ResultSet getGeneratedKeys() throws SQLException {
      throw new UnsupportedOperationException();
   }
}
