Main Page | Packages | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

DriverResultSet.java

00001 /**
00002  * C-JDBC: Clustered JDBC.
00003  * Copyright (C) 2002-2005 French National Institute For Research In Computer
00004  * Science And Control (INRIA).
00005  * Contact: c-jdbc@objectweb.org
00006  * 
00007  * This library is free software; you can redistribute it and/or modify it
00008  * under the terms of the GNU Lesser General Public License as published by the
00009  * Free Software Foundation; either version 2.1 of the License, or any later
00010  * version.
00011  * 
00012  * This library is distributed in the hope that it will be useful, but WITHOUT
00013  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
00015  * for more details.
00016  * 
00017  * You should have received a copy of the GNU Lesser General Public License
00018  * along with this library; if not, write to the Free Software Foundation,
00019  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00020  *
00021  * Initial developer(s): Mark Matthews. 
00022  * Contributor(s): Emmanuel Cecchet, Andre Austin, Marc Wick, Jean-Bernard van Zuylen.
00023  */
00024 
00025 package org.objectweb.cjdbc.driver;
00026 
00027 import java.io.ByteArrayInputStream;
00028 import java.io.IOException;
00029 import java.io.InputStream;
00030 import java.io.ObjectInputStream;
00031 import java.math.BigDecimal;
00032 import java.math.BigInteger;
00033 import java.sql.PreparedStatement;
00034 import java.sql.ResultSet;
00035 import java.sql.SQLException;
00036 import java.sql.SQLWarning;
00037 import java.sql.Time;
00038 import java.sql.Timestamp;
00039 import java.util.ArrayList;
00040 import java.util.Calendar;
00041 import java.util.Hashtable;
00042 
00043 import org.objectweb.cjdbc.common.sql.NotImplementedException;
00044 
00045 /**
00046  * A <code>ResultSet</code> provides access to a table of data generated by
00047  * executing a Statement. The table rows are retrieved in sequence. Within a row
00048  * its column values can be accessed in any order.
00049  * <p>
00050  * A <code>ResultSet</code> maintains a cursor pointing to its current row of
00051  * data. Initially the cursor is positioned before the first row. The 'next'
00052  * method moves the cursor to the next row.
00053  * <p>
00054  * The <code>getXXX</code> methods retrieve column values for the current row.
00055  * You can retrieve values either using the index number of the column, or by
00056  * using the name of the column. In general using the column index will be more
00057  * efficient. Columns are numbered from 1.
00058  * <p>
00059  * For maximum portability, <code>ResultSet</code> columns within each row
00060  * should be read in left-to-right order and each column should be read only
00061  * once.
00062  * <p>
00063  * For the <code>getXXX</code> methods, the JDBC driver attempts to convert
00064  * the underlying data to the specified Java type and returns a suitable Java
00065  * value. See the JDBC specification for allowable mappings from SQL types to
00066  * Java types with the <code>ResultSet</code> <code>getXXX</code> methods.
00067  * <p>
00068  * Column names used as input to <code>getXXX</code> methods are case
00069  * insenstive. When performing a <code>getXXX</code> using a column name, if
00070  * several columns have the same name, then the value of the first matching
00071  * column will be returned. The column name option is designed to be used when
00072  * column names are used in the SQL Query. For columns that are NOT explicitly
00073  * named in the query, it is best to use column numbers. If column names were
00074  * used there is no way for the programmer to guarentee that they actually refer
00075  * to the intended columns.
00076  * <P>
00077  * A <code>ResultSet</code> is automatically closed by the
00078  * <code>Statement</code> that generated it when that <code>Statement</code>
00079  * is closed, re-executed, or is used to retrieve the next result from a
00080  * sequence of multiple results.
00081  * <P>
00082  * The number, types and properties of a ResultSet's columns are provided by the
00083  * <code>ResultSetMetaData</code> object returned by the
00084  * <code>getMetaData</code> method.
00085  * 
00086  * @see java.sql.ResultSetMetaData
00087  * @see java.sql.ResultSet
00088  * @author Mark Matthews <mmatthew@worldserver.com>
00089  * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
00090  * @author <a href="mailto:alexander.laamanen@tecnomen.com">Alexander Laamanen
00091  *         </a>
00092  * @author <a href="mailto:Nicolas.Modrzyk@inrialpes.fr">Nicolas Modrzyk </a>
00093  * @author <a href="mailto:jbvanzuylen@transwide.com">Jean-Bernard van Zuylen
00094  *         </a>
00095  * @version 1.0
00096  */
00097 public class DriverResultSet
00098     implements
00099       java.sql.ResultSet,
00100       java.io.Serializable,
00101       java.lang.Cloneable
00102 {
00103   /** Cursor to current row */
00104   protected int                       currentRow            = -1;
00105   /** Number of rows */
00106   protected int                       nbOfRows              = -1;
00107   /** Number of columns */
00108   protected int                       nbOfColumns           = -1;
00109   /** The results */
00110   protected ArrayList                 data;
00111   /** True if there is more data to fetch from the controller */
00112   private boolean                     hasMoreData;
00113   /** The fetch direction (not used yet) */
00114   protected int                       fetchDirection        = FETCH_FORWARD;
00115   /** The fetch size */
00116   protected int                       fetchSize             = 0;
00117   /** ResultSet cursor name */
00118   private String                      cursorName;
00119 
00120   /** The fields */
00121   protected Field[]                   fields;
00122   /** for wasNull() */
00123   protected boolean                   wasNullFlag           = false;
00124   /** column name -> index in ResultSet data array */
00125   protected transient Hashtable       columnNameToIndex     = null;
00126   /** full column name -> index in ResultSet data array */
00127   protected transient Hashtable       fullColumnNameToIndex = null;
00128 
00129   /** Type of ResultSet */
00130   protected int                       resultSetType         = 0;
00131   /** Concurrency for this ResultSet */
00132   protected int                       resultSetConcurrency  = 0;
00133   /** the warning chain */
00134   protected SQLWarning                warnings              = null;
00135   /** Statement corresponding to this ResultSet */
00136   protected transient Statement       owningStatement;
00137 
00138   private boolean                     isClosed              = true;
00139 
00140   /** Statement for deleting rows with Updatable ResultSets * */
00141   private transient PreparedStatement deleteStatement       = null;
00142   /** Statement for inserting rows with Updatable ResultSets * */
00143   private transient PreparedStatement insertStatement       = null;
00144   /** Statement for refreshing rows with Updatable ResultSets * */
00145   private transient PreparedStatement refreshStatement      = null;
00146   /** Statement for updating rows with Updatable ResultSets * */
00147   private transient PreparedStatement updateStatement       = null;
00148   /** Indicates whether cursor is on the insert row * */
00149   private transient boolean           inserting             = false;
00150   /** Indicates if the current row is being updated * */
00151   private transient boolean           updating              = false;
00152   /** Temporary object for not yet comitted ResultSet updates * */
00153   private transient Object[]          tempRow               = null;
00154   /** Cache the columns forming the primary key * */
00155   private transient String[]          primaryKeyColumns     = null;
00156 
00157   private static final String         UPDATEABLE_MESSAGE    = "ResultSet not updateable. The "
00158                                                                 + "query that generated this result set must select only one table, and must "
00159                                                                 + "select all primary keys from that table. See the JDBC 2.1 API Specification, "
00160                                                                 + "section 5.6 for more details.";
00161 
00162   //---------------------------------------------------------------------
00163   // Traversal/Positioning
00164   //---------------------------------------------------------------------
00165 
00166   /**
00167    * A ResultSet is initially positioned before its first row, the first call to
00168    * next makes the first row the current row; the second call makes the second
00169    * row the current row, etc.
00170    * <p>
00171    * If an input stream from the previous row is open, it is implicitly closed.
00172    * The ResultSet's warning chain is cleared when a new row is read
00173    * 
00174    * @return <code>true</code> if the new current is valid; <code>false</code>
00175    *         if there are no more rows
00176    * @exception java.sql.SQLException if a database access error occurs
00177    */
00178   public boolean next() throws java.sql.SQLException
00179   {
00180     checkIfClosed();
00181 
00182     if (inserting)
00183     {
00184       insertStatement.clearParameters();
00185       tempRow = null;
00186       inserting = false;
00187     }
00188 
00189     if (updating)
00190       cancelRowUpdates();
00191     
00192     if (nbOfRows == 0)
00193       return false;
00194     
00195     if (currentRow + 1 >= nbOfRows)
00196     {
00197       if (hasMoreData)
00198       {
00199         owningStatement.connection.fetchNextData(cursorName, fetchSize, this);
00200         currentRow = 0;
00201         if (data == null)
00202         {
00203           nbOfRows = 0;
00204           return false;
00205         }
00206         else
00207         {
00208           nbOfRows = data.size();
00209           return true;
00210         }
00211       }
00212       
00213       // force scroll past end
00214       currentRow = nbOfRows;
00215       return false;
00216     }
00217     
00218     clearWarnings();
00219     currentRow++;
00220     return true;
00221   }
00222 
00223   /**
00224    * The prev method is not part of JDBC, but because of the architecture of
00225    * this driver it is possible to move both forward and backward within the
00226    * result set.
00227    * <p>
00228    * If an input stream from the previous row is open, it is implicitly closed.
00229    * The ResultSet's warning chain is cleared when a new row is read
00230    * 
00231    * @return <code>true</code> if the new current is valid; <code>false</code>
00232    *         if there are no more rows
00233    * @exception SQLException if a database access error occurs
00234    */
00235   public boolean prev() throws SQLException
00236   {
00237     checkIfClosed();
00238     
00239     if (inserting)
00240     {
00241       insertStatement.clearParameters();
00242       tempRow = null;
00243       inserting = false;
00244     }
00245 
00246     if (updating)
00247       cancelRowUpdates();
00248     
00249     if (currentRow - 1 >= 0)
00250     {
00251       currentRow--;
00252       return true;
00253     }
00254     
00255     return false;
00256   }
00257 
00258   /**
00259    * JDBC 2.0.
00260    * <p>
00261    * Determine if the cursor is before the first row in the result set.
00262    * 
00263    * @return <code>true</code> if before the first row, <code>false</code>
00264    *         otherwise. Returns <code>false</code> when the result set
00265    *         contains no rows.
00266    * @exception SQLException if a database-access error occurs.
00267    */
00268   public boolean isBeforeFirst() throws SQLException
00269   {
00270     checkIfClosed();
00271     if (nbOfRows == 0)
00272       return false;
00273     else
00274       return (currentRow == -1);
00275   }
00276 
00277   /**
00278    * JDBC 2.0
00279    * <p>
00280    * Determine if the cursor is after the last row in the result set.
00281    * 
00282    * @return <code>true</code> if after the last row, <code>false</code>
00283    *         otherwise. Returns <code>false</code> when the result set
00284    *         contains no rows.
00285    * @exception SQLException if a database-access error occurs.
00286    */
00287   public boolean isAfterLast() throws SQLException
00288   {
00289     checkIfClosed();
00290     if (nbOfRows == 0)
00291       return false;
00292     else
00293       return (currentRow >= nbOfRows);
00294   }
00295 
00296   /**
00297    * JDBC 2.0
00298    * <p>
00299    * Determine if the cursor is on the first row of the result set.
00300    * 
00301    * @return <code>true</code> if on the first row, <code>false</code>
00302    *         otherwise.
00303    * @exception SQLException if a database-access error occurs.
00304    */
00305   public boolean isFirst() throws SQLException
00306   {
00307     checkIfClosed();
00308     if (nbOfRows == 0)
00309       return false;
00310     else
00311       return (currentRow == 0);
00312   }
00313 
00314   /**
00315    * JDBC 2.0
00316    * <p>
00317    * Determine if the cursor is on the last row of the result set. Note: Calling
00318    * isLast() may be expensive since the JDBC driver might need to fetch ahead
00319    * one row in order to determine whether the current row is the last row in
00320    * the result set.
00321    * 
00322    * @return <code>true</code> if on the last row, <code>false</code>
00323    *         otherwise.
00324    * @exception SQLException if a database-access error occurs.
00325    */
00326   public boolean isLast() throws SQLException
00327   {
00328     checkIfClosed();
00329     if (nbOfRows == 0)
00330       return false;
00331     else
00332       return (currentRow == nbOfRows - 1);
00333   }
00334 
00335   /**
00336    * JDBC 2.0
00337    * <p>
00338    * Moves to the front of the result set, just before the first row. Has no
00339    * effect if the result set contains no rows.
00340    * 
00341    * @exception SQLException if a database-access error occurs, or result set
00342    *              type is TYPE_FORWARD_ONLY
00343    */
00344   public void beforeFirst() throws SQLException
00345   {
00346     checkIfClosed();
00347     
00348     if (inserting)
00349     {
00350       insertStatement.clearParameters();
00351       tempRow = null;
00352       inserting = false;
00353     }
00354 
00355     if (updating)
00356       cancelRowUpdates();
00357     
00358     currentRow = -1;
00359   }
00360 
00361   /**
00362    * JDBC 2.0
00363    * <p>
00364    * Moves to the end of the result set, just after the last row. Has no effect
00365    * if the result set contains no rows.
00366    * 
00367    * @exception SQLException if a database-access error occurs, or result set
00368    *              type is TYPE_FORWARD_ONLY.
00369    */
00370   public void afterLast() throws SQLException
00371   {
00372     checkIfClosed();
00373     
00374     if (inserting)
00375     {
00376       insertStatement.clearParameters();
00377       tempRow = null;
00378       inserting = false;
00379     }
00380 
00381     if (updating)
00382       cancelRowUpdates();
00383 
00384     if (nbOfRows != 0)
00385       currentRow = nbOfRows;
00386   }
00387 
00388   /**
00389    * JDBC 2.0
00390    * <p>
00391    * Moves to the first row in the result set.
00392    * 
00393    * @return <code>true</code> if on a valid row, false if no rows in the
00394    *         result set.
00395    * @exception SQLException if a database-access error occurs, or result set
00396    *              type is TYPE_FORWARD_ONLY.
00397    */
00398   public boolean first() throws SQLException
00399   {
00400     checkIfClosed();
00401     
00402     if (inserting)
00403     {
00404       insertStatement.clearParameters();
00405       tempRow = null;
00406       inserting = false;
00407     }
00408 
00409     if (updating)
00410       cancelRowUpdates();
00411 
00412     if (nbOfRows == 0)
00413       return false;
00414 
00415     currentRow = 0;
00416     return true;
00417   }
00418 
00419   /**
00420    * JDBC 2.0
00421    * <p>
00422    * Moves to the last row in the result set.
00423    * 
00424    * @return <code>true</code> if on a valid row, false if no rows in the
00425    *         result set.
00426    * @exception SQLException if a database-access error occurs, or result set
00427    *              type is TYPE_FORWARD_ONLY.
00428    */
00429   public boolean last() throws SQLException
00430   {
00431     checkIfClosed();
00432 
00433     if (inserting)
00434     {
00435       insertStatement.clearParameters();
00436       tempRow = null;
00437       inserting = false;
00438     }
00439 
00440     if (updating)
00441       cancelRowUpdates();
00442 
00443     if (nbOfRows == 0)
00444       return false;
00445 
00446     currentRow = nbOfRows - 1;
00447     return true;
00448   }
00449 
00450   /**
00451    * JDBC 2.0
00452    * <p>
00453    * Determine the current row number. The first row is number 1, the second
00454    * number 2, etc.
00455    * 
00456    * @return the current row number, else return 0 if there is no current row
00457    * @exception SQLException if a database-access error occurs.
00458    */
00459   public int getRow() throws SQLException
00460   {
00461     checkIfClosed();
00462     if (currentRow < 0 || currentRow >= nbOfRows || nbOfRows == 0)
00463       return 0;
00464     else
00465       return currentRow + 1;
00466   }
00467 
00468   /**
00469    * JDBC 2.0
00470    * <p>
00471    * Move to an absolute row number in the result set.
00472    * <p>
00473    * If row is positive, moves to an absolute row with respect to the beginning
00474    * of the result set. The first row is row 1, the second is row 2, etc.
00475    * <p>
00476    * If row is negative, moves to an absolute row position with respect to the
00477    * end of result set. For example, calling absolute(-1) positions the cursor
00478    * on the last row, absolute(-2) indicates the next-to-last row, etc.
00479    * <p>
00480    * An attempt to position the cursor beyond the first/last row in the result
00481    * set, leaves the cursor before/after the first/last row, respectively.
00482    * <p>
00483    * Note: Calling absolute(1) is the same as calling first(). Calling
00484    * absolute(-1) is the same as calling last().
00485    * 
00486    * @param row the row to move to
00487    * @return <code>true</code> if on the result set, false if off.
00488    * @exception SQLException if a database-access error occurs, or row is 0, or
00489    *              result set type is TYPE_FORWARD_ONLY.
00490    */
00491   public boolean absolute(int row) throws SQLException
00492   {
00493     checkIfClosed();
00494 
00495     if (inserting)
00496     {
00497       insertStatement.clearParameters();
00498       tempRow = null;
00499       inserting = false;
00500     }
00501 
00502     if (updating)
00503       cancelRowUpdates();
00504 
00505     if (nbOfRows == 0)
00506       return false;
00507 
00508     if (row == 0)
00509       throw new SQLException("Cannot absolute position to row 0");
00510 
00511     if (row == 1)
00512       return first();
00513 
00514     if (row == -1)
00515       return last();
00516 
00517     if (row > nbOfRows)
00518     {
00519       afterLast();
00520       return false;
00521     }
00522 
00523     if (row < 0)
00524     { // adjust to reflect after end of result set
00525       int newRowPosition = nbOfRows + row + 1;
00526 
00527       if (newRowPosition <= 0)
00528       {
00529         beforeFirst();
00530         return false;
00531       }
00532 
00533       return absolute(newRowPosition);
00534     }
00535     else
00536     {
00537       row--; // adjust for index difference
00538       currentRow = row;
00539       return true;
00540     }
00541   }
00542 
00543   /**
00544    * JDBC 2.0
00545    * <p>
00546    * Moves a relative number of rows, either positive or negative. Attempting to
00547    * move beyond the first/last row in the result set positions the cursor
00548    * before/after the the first/last row. Calling relative(0) is valid, but does
00549    * not change the cursor position.
00550    * <p>
00551    * Note: Calling relative(1) is different than calling next() since is makes
00552    * sense to call next() when there is no current row, for example, when the
00553    * cursor is positioned before the first row or after the last row of the
00554    * result set.
00555    * 
00556    * @param rows the number of rows
00557    * @return <code>true</code> if on a row, false otherwise.
00558    * @exception SQLException if a database-access error occurs, or there is no
00559    *              current row, or result set type is TYPE_FORWARD_ONLY.
00560    */
00561   public boolean relative(int rows) throws SQLException
00562   {
00563     checkIfClosed();
00564 
00565     if (inserting)
00566     {
00567       insertStatement.clearParameters();
00568       tempRow = null;
00569       inserting = false;
00570     }
00571 
00572     if (updating)
00573       cancelRowUpdates();
00574 
00575     if (nbOfRows == 0)
00576       return false;
00577 
00578     return absolute(currentRow + rows + 1);
00579   }
00580 
00581   /**
00582    * JDBC 2.0
00583    * <p>
00584    * Moves to the previous row in the result set.
00585    * <p>
00586    * Note: previous() is not the same as relative(-1) since it makes sense to
00587    * call previous() when there is no current row.
00588    * 
00589    * @return <code>true</code> if on a valid row, false if off the result set.
00590    * @exception SQLException if a database-access error occurs, or result set
00591    *              type is TYPE_FORWAR_DONLY.
00592    */
00593   public boolean previous() throws SQLException
00594   {
00595     return prev();
00596   }
00597 
00598   /**
00599    * JDBC 2.0 Give a hint as to the direction in which the rows in this result
00600    * set will be processed. The initial value is determined by the statement
00601    * that produced the result set. The fetch direction may be changed at any
00602    * time.
00603    * 
00604    * @param direction the fetch direction
00605    * @exception SQLException if a database-access error occurs, or the result
00606    *              set type is TYPE_FORWARD_ONLY and direction is not
00607    *              FETCH_FORWARD. MM.MySQL actually ignores this, because it has
00608    *              the whole result set anyway, so the direction is immaterial.
00609    */
00610   public void setFetchDirection(int direction) throws SQLException
00611   {
00612     if (direction != FETCH_FORWARD && direction != FETCH_REVERSE)
00613       throw new SQLException("Illegal value for fetch direction");
00614     else
00615       fetchDirection = direction;
00616   }
00617 
00618   /**
00619    * JDBC 2.0 Return the fetch direction for this result set.
00620    * 
00621    * @return the fetch direction
00622    * @exception SQLException if a database-access error occurs
00623    */
00624   public int getFetchDirection() throws SQLException
00625   {
00626     return fetchDirection;
00627   }
00628 
00629   /**
00630    * JDBC 2.0 Give the JDBC driver a hint as to the number of rows that should
00631    * be fetched from the database when more rows are needed for this result set.
00632    * If the fetch size specified is zero, then the JDBC driver ignores the
00633    * value, and is free to make its own best guess as to what the fetch size
00634    * should be. The default value is set by the statement that creates the
00635    * result set. The fetch size may be changed at any time.
00636    * 
00637    * @param rows the number of rows to fetch
00638    * @exception SQLException if a database-access error occurs, or the condition
00639    *              0 <= rows <= this.getMaxRows() is not satisfied. Currently
00640    *              ignored by this driver.
00641    */
00642   public void setFetchSize(int rows) throws SQLException
00643   {
00644     if (rows < 0 || rows > nbOfRows)
00645       throw new SQLException("Value must be between 0 and getMaxRows()");
00646     fetchSize = rows;
00647   }
00648 
00649   /**
00650    * JDBC 2.0 Return the fetch size for this result set.
00651    * 
00652    * @return the fetch size
00653    * @exception SQLException if a database-access error occurs
00654    */
00655   public int getFetchSize() throws SQLException
00656   {
00657     return fetchSize;
00658   }
00659 
00660   //
00661   //---------------------------------------------------------------------
00662   // Getter's and Setter's
00663   //---------------------------------------------------------------------
00664   //
00665 
00666   /**
00667    * Get the value of a column in the current row as a Java String
00668    * 
00669    * @param columnIndex the first column is 1, the second is 2...
00670    * @return the column value, null for SQL NULL
00671    * @exception SQLException if a database access error occurs
00672    */
00673   public String getString(int columnIndex) throws SQLException
00674   {
00675     checkRowAndColPosAndSetNullFlag(columnIndex);
00676 
00677     if (wasNullFlag)
00678       return null;
00679 
00680     if (inserting || updating)
00681       return tempRow[columnIndex - 1].toString();
00682     else
00683       return (((Object[]) data.get(currentRow))[columnIndex - 1]).toString();
00684   }
00685 
00686   /**
00687    * Get the value of a column in the current row as a Java boolean
00688    * 
00689    * @param columnIndex the first column is 1, the second is 2...
00690    * @return the column value, false for SQL NULL
00691    * @exception SQLException if a database access error occurs
00692    */
00693   public boolean getBoolean(int columnIndex) throws SQLException
00694   {
00695     checkRowAndColPosAndSetNullFlag(columnIndex);
00696 
00697     if (wasNullFlag)
00698       return false;
00699 
00700     Object object;
00701     if (inserting || updating)
00702       object = tempRow[columnIndex - 1];
00703     else
00704       object = (((Object[]) data.get(currentRow))[columnIndex - 1]);
00705 
00706     String stringVal = object.toString();
00707     if ((stringVal != null) && (stringVal.length() > 0))
00708     {
00709       stringVal = stringVal.toLowerCase();
00710 
00711       // first we check the connection values to be consistent
00712       if (owningStatement.connection.getPreparedStatementBooleanTrue().equals(
00713           stringVal))
00714       {
00715         return true;
00716       }
00717       else if (owningStatement.connection.getPreparedStatementBooleanFalse()
00718           .equals(stringVal))
00719       {
00720         return false;
00721       }
00722 
00723       // now we check some other possible string representations of boolean
00724       else if ("t".equals(stringVal))
00725       {
00726         return true;
00727       }
00728       else if ("f".equals(stringVal))
00729       {
00730         return false;
00731       }
00732       else if ("true".equals(stringVal))
00733       {
00734         return true;
00735       }
00736       else if ("false".equals(stringVal))
00737       {
00738         return false;
00739       }
00740       else if ("1".equals(stringVal))
00741       {
00742         return true;
00743       }
00744       else if ("0".equals(stringVal))
00745       {
00746         return false;
00747       }
00748       else if ("y".equals(stringVal))
00749       {
00750         return true;
00751       }
00752       else if ("n".equals(stringVal))
00753       {
00754         return false;
00755       }
00756       else if ("yes".equals(stringVal))
00757       {
00758         return true;
00759       }
00760       else if ("no".equals(stringVal))
00761       {
00762         return false;
00763       }
00764 
00765       // we didn't find anything reasonable and throw an exception
00766       throw new SQLException("column value " + stringVal
00767           + " could not be converted to boolean");
00768     }
00769     else
00770     {
00771       return false;
00772     }
00773   }
00774 
00775   /**
00776    * Get the value of a column in the current row as a Java short.
00777    * 
00778    * @param columnIndex the first column is 1, the second is 2,...
00779    * @return the column value; 0 if SQL NULL
00780    * @exception SQLException if a database access error occurs
00781    */
00782   public short getShort(int columnIndex) throws SQLException
00783   {
00784     checkRowAndColPosAndSetNullFlag(columnIndex);
00785 
00786     if (wasNullFlag)
00787       return 0;
00788 
00789     Object obj;
00790     if (inserting || updating)
00791       obj = tempRow[columnIndex - 1];
00792     else
00793       obj = ((Object[]) data.get(currentRow))[columnIndex - 1];
00794 
00795     if (obj instanceof Number)
00796     {
00797       return ((Number) obj).shortValue();
00798     }
00799 
00800     // the object is not of type number we parse the string representation
00801     try
00802     {
00803       String string = obj.toString();
00804       string = string.trim();
00805       return Short.parseShort(string);
00806     }
00807     catch (NumberFormatException e)
00808     {
00809       throw new SQLException("the value " + obj.toString()
00810           + " is not a valid short number");
00811     }
00812   }
00813 
00814   /**
00815    * Get the value of a column in the current row as a Java int.
00816    * 
00817    * @param columnIndex the first column is 1, the second is 2,...
00818    * @return the column value; 0 if SQL NULL
00819    * @exception SQLException if a database access error occurs
00820    */
00821   public int getInt(int columnIndex) throws SQLException
00822   {
00823     checkRowAndColPosAndSetNullFlag(columnIndex);
00824 
00825     if (wasNullFlag)
00826       return 0;
00827 
00828     Object obj;
00829     if (inserting || updating)
00830       obj = tempRow[columnIndex - 1];
00831     else
00832       obj = ((Object[]) data.get(currentRow))[columnIndex - 1];
00833 
00834     if (obj instanceof Number)
00835     {
00836       return ((Number) obj).intValue();
00837     }
00838 
00839     // the object is not of type number we parse the string representation
00840     try
00841     {
00842       String string = obj.toString();
00843       string = string.trim();
00844       return Integer.parseInt(string);
00845     }
00846     catch (NumberFormatException e)
00847     {
00848       throw new SQLException("the value " + obj.toString()
00849           + " is not a valid int number");
00850     }
00851   }
00852 
00853   /**
00854    * Get the value of a column in the current row as a Java long.
00855    * 
00856    * @param columnIndex the first column is 1, the second is 2,...
00857    * @return the column value; 0 if SQL NULL
00858    * @exception SQLException if a database access error occurs
00859    */
00860   public long getLong(int columnIndex) throws SQLException
00861   {
00862     checkRowAndColPosAndSetNullFlag(columnIndex);
00863 
00864     if (wasNullFlag)
00865       return 0;
00866 
00867     Object obj;
00868     if (inserting || updating)
00869       obj = tempRow[columnIndex - 1];
00870     else
00871       obj = ((Object[]) data.get(currentRow))[columnIndex - 1];
00872 
00873     if (obj instanceof Number)
00874     {
00875       return ((Number) obj).longValue();
00876     }
00877 
00878     // the object is not of type number we parse the string representation
00879     try
00880     {
00881       String string = obj.toString();
00882       string = string.trim();
00883       return Long.parseLong(string);
00884     }
00885     catch (NumberFormatException e)
00886     {
00887       throw new SQLException("the value " + obj.toString()
00888           + " is not a valid long number");
00889     }
00890   }
00891 
00892   /**
00893    * Get the value of a column in the current row as a Java float.
00894    * 
00895    * @param columnIndex the first column is 1, the second is 2,...
00896    * @return the column value; 0 if SQL NULL
00897    * @exception SQLException if a database access error occurs
00898    */
00899   public float getFloat(int columnIndex) throws SQLException
00900   {
00901     checkRowAndColPosAndSetNullFlag(columnIndex);
00902 
00903     if (wasNullFlag)
00904       return 0;
00905 
00906     Object obj;
00907     if (inserting || updating)
00908       obj = tempRow[columnIndex - 1];
00909     else
00910       obj = ((Object[]) data.get(currentRow))[columnIndex - 1];
00911 
00912     if (obj instanceof Number)
00913     {
00914       return ((Number) obj).floatValue();
00915     }
00916 
00917     // the object is not of type number we parse the string representation
00918     try
00919     {
00920       String string = obj.toString();
00921       string = string.trim();
00922       return Float.parseFloat(string);
00923     }
00924     catch (NumberFormatException e)
00925     {
00926       throw new SQLException("the value " + obj.toString()
00927           + " is not a valid float number");
00928     }
00929   }
00930 
00931   /**
00932    * Get the value of a column in the current row as a Java double.
00933    * 
00934    * @param columnIndex the first column is 1, the second is 2,...
00935    * @return the column value; 0 if SQL NULL
00936    * @exception SQLException if a database access error occurs
00937    */
00938   public double getDouble(int columnIndex) throws SQLException
00939   {
00940     checkRowAndColPosAndSetNullFlag(columnIndex);
00941 
00942     if (wasNullFlag)
00943       return 0;
00944 
00945     Object obj;
00946     if (inserting || updating)
00947       obj = tempRow[columnIndex - 1];
00948     else
00949       obj = ((Object[]) data.get(currentRow))[columnIndex - 1];
00950 
00951     if (obj instanceof Number)
00952     {
00953       return ((Number) obj).doubleValue();
00954     }
00955 
00956     // the object is not of type number we parse the string representation
00957     try
00958     {
00959       String string = obj.toString();
00960       string = string.trim();
00961       return Double.parseDouble(string);
00962     }
00963     catch (NumberFormatException e)
00964     {
00965       throw new SQLException("the value " + obj.toString()
00966           + " is not a valid double number");
00967     }
00968   }
00969 
00970   /**
00971    * Get the value of a column in the current row as a java.lang.BigDecimal
00972    * object
00973    * 
00974    * @param columnIndex the first column is 1, the second is 2...
00975    * @param scale the number of digits to the right of the decimal
00976    * @return the column value; if the value is SQL NULL, null
00977    * @exception SQLException if a database access error occurs
00978    * @deprecated
00979    */
00980   public BigDecimal getBigDecimal(int columnIndex, int scale)
00981       throws SQLException
00982   {
00983     BigDecimal bigDecimal = getBigDecimal(columnIndex);
00984     if (bigDecimal == null)
00985       return null;
00986     else
00987       return bigDecimal.setScale(scale);
00988   }
00989 
00990   /**
00991    * Get the value of a column in the current row as a Java byte array.
00992    * <p>
00993    * <b>Be warned </b> If the blob is huge, then you may run out of memory.
00994    * 
00995    * @param columnIndex the first column is 1, the second is 2, ...
00996    * @return the column value; if the value is SQL NULL, the result is null
00997    * @exception SQLException if a database access error occurs
00998    */
00999   public byte[] getBytes(int columnIndex) throws SQLException
01000   {
01001     checkRowAndColPosAndSetNullFlag(columnIndex);
01002 
01003     if (wasNullFlag)
01004       return null;
01005 
01006     Object o;
01007     if (inserting || updating)
01008       o = tempRow[columnIndex - 1];
01009     else
01010       o = ((Object[]) data.get(currentRow))[columnIndex - 1];
01011 
01012     byte[] tmp;
01013     if (o instanceof java.lang.String)
01014     {
01015       tmp = ((String) o).getBytes();
01016     }
01017     else
01018     {
01019       tmp = (byte[]) o;
01020     }
01021 
01022     if (((Connection) owningStatement.getConnection()).isDriverProcessed())
01023       return owningStatement.connection.getBlobFilter().decode(tmp);
01024     else
01025       return tmp;
01026   }
01027 
01028   /**
01029    * Get the value of a column in the current row as a java.sql.Date object
01030    * 
01031    * @param columnIndex the first column is 1, the second is 2...
01032    * @return the column value; null if SQL NULL
01033    * @exception SQLException if a database access error occurs
01034    */
01035   public java.sql.Date getDate(int columnIndex) throws SQLException
01036   {
01037     checkRowAndColPosAndSetNullFlag(columnIndex);
01038 
01039     if (wasNullFlag)
01040       return null;
01041 
01042     // we may be reading a timestamp column and have to convert it to date
01043     // the client is asking for the date field only, we have to make sure
01044     // hour,minutes,... are cleared
01045     String dateString;
01046     if (inserting || updating)
01047       dateString = tempRow[columnIndex - 1].toString();
01048     else
01049       dateString = ((Object[]) data.get(currentRow))[columnIndex - 1]
01050           .toString();
01051 
01052     if (dateString.length() == 10)
01053       return java.sql.Date.valueOf(dateString);
01054     else
01055       return java.sql.Date.valueOf(dateString.substring(0, 10));
01056   }
01057 
01058   /**
01059    * Get the value of a column in the current row as a java.sql.Time object
01060    * 
01061    * @param columnIndex the first column is 1, the second is 2...
01062    * @return the column value; null if SQL NULL
01063    * @exception SQLException if a database access error occurs
01064    */
01065   public Time getTime(int columnIndex) throws SQLException
01066   {
01067     checkRowAndColPosAndSetNullFlag(columnIndex);
01068 
01069     if (wasNullFlag)
01070       return null;
01071 
01072     Object obj;
01073     if (inserting || updating)
01074       obj = tempRow[columnIndex - 1];
01075     else
01076       obj = ((Object[]) data.get(currentRow))[columnIndex - 1];
01077 
01078     if (obj instanceof java.util.Date)
01079     {
01080       java.util.Date time = (java.util.Date) obj;
01081       // the driver returns the format of the column, but we are asking for
01082       // the time values only.
01083       String timeString = time.toString();
01084       if (timeString.length() == 8)
01085       {
01086         // ok we have got a timefield of the format HH:mm:ss, exactly the way
01087         // we need it, no further processing is required
01088         return new Time(time.getTime());
01089       }
01090 
01091       // we have got the date fields too and have to clear the year, month and
01092       // date field
01093       Calendar cal = Calendar.getInstance();
01094       cal.setTime(time);
01095       cal.clear(Calendar.YEAR);
01096       cal.clear(Calendar.MONTH);
01097       cal.clear(Calendar.DATE);
01098       cal.clear(Calendar.MILLISECOND);
01099       return new Time(cal.getTimeInMillis());
01100     }
01101 
01102     // the object is not of type date we parse the string representation
01103     try
01104     {
01105       String string = obj.toString();
01106       string = string.trim();
01107       return Time.valueOf(string);
01108     }
01109     catch (IllegalArgumentException e)
01110     {
01111       throw new SQLException("the value " + obj.toString()
01112           + " is not a valid time");
01113     }
01114   }
01115 
01116   /**
01117    * Get the value of a column in the current row as a java.sql.Timestamp object
01118    * 
01119    * @param columnIndex the first column is 1, the second is 2...
01120    * @return the column value; null if SQL NULL
01121    * @exception SQLException if a database access error occurs
01122    */
01123   public Timestamp getTimestamp(int columnIndex) throws SQLException
01124   {
01125     checkRowAndColPosAndSetNullFlag(columnIndex);
01126 
01127     if (wasNullFlag)
01128       return null;
01129 
01130     Object obj;
01131     if (inserting || updating)
01132       obj = tempRow[columnIndex - 1];
01133     else
01134       obj = ((Object[]) data.get(currentRow))[columnIndex - 1];
01135 
01136     if (obj instanceof java.util.Date)
01137     {
01138       return new Timestamp(((java.util.Date) obj).getTime());
01139     }
01140 
01141     // the object is not of type timestamp we parse the string representation
01142     try
01143     {
01144       String string = obj.toString();
01145       string = string.trim();
01146       return Timestamp.valueOf(string);
01147     }
01148     catch (IllegalArgumentException e)
01149     {
01150       throw new SQLException("the value " + obj.toString()
01151           + " is not a valid timestamp");
01152     }
01153   }
01154 
01155   /**
01156    * A column value can be retrieved as a stream of ASCII characters and then
01157    * read in chunks from the stream. This method is particulary suitable for
01158    * retrieving large LONGVARCHAR values. The JDBC driver will do any necessary
01159    * conversion from the database format into ASCII.
01160    * <p>
01161    * <B>Note: </B> All the data in the returned stream must be read prior to
01162    * getting the value of any other column. The next call to a get method
01163    * implicitly closes the stream. Also, a stream may return 0 for available()
01164    * whether there is data available or not.
01165    * 
01166    * @param columnIndex the first column is 1, the second is 2, ...
01167    * @return a Java InputStream that delivers the database column value as a
01168    *         stream of one byte ASCII characters. If the value is SQL NULL then
01169    *         the result is null
01170    * @exception SQLException if a database access error occurs
01171    * @see #getBinaryStream(int)
01172    */
01173   public InputStream getAsciiStream(int columnIndex) throws SQLException
01174   {
01175     checkRowAndColPosAndSetNullFlag(columnIndex);
01176 
01177     return getBinaryStream(columnIndex);
01178   }
01179 
01180   /**
01181    * A column value can also be retrieved as a stream of Unicode characters. We
01182    * implement this as a binary stream.
01183    * 
01184    * @param columnIndex the first column is 1, the second is 2...
01185    * @return a Java InputStream that delivers the database column value as a
01186    *         stream of two byte Unicode characters. If the value is SQL NULL,
01187    *         then the result is null
01188    * @exception SQLException if a database access error occurs
01189    * @deprecated
01190    * @see #getAsciiStream
01191    * @see #getBinaryStream(int)
01192    */
01193   public InputStream getUnicodeStream(int columnIndex) throws SQLException
01194   {
01195     checkRowAndColPosAndSetNullFlag(columnIndex);
01196 
01197     return getBinaryStream(columnIndex);
01198   }
01199 
01200   /**
01201    * A column value can also be retrieved as a binary strea. This method is
01202    * suitable for retrieving LONGVARBINARY values.
01203    * 
01204    * @param columnIndex the first column is 1, the second is 2...
01205    * @return a Java InputStream that delivers the database column value as a
01206    *         stream of bytes. If the value is SQL NULL, then the result is null
01207    * @exception SQLException if a database access error occurs
01208    * @see #getAsciiStream(int)
01209    * @see #getUnicodeStream(int)
01210    */
01211 
01212   public InputStream getBinaryStream(int columnIndex) throws SQLException
01213   {
01214     checkRowAndColPosAndSetNullFlag(columnIndex);
01215 
01216     byte b[] = getBytes(columnIndex);
01217     if (b != null)
01218       return new ByteArrayInputStream(b);
01219     else
01220       return null; // SQL NULL
01221   }
01222 
01223   /**
01224    * The following routines simply convert the columnName into a columnIndex and
01225    * then call the appropriate routine above.
01226    * 
01227    * @param columnName is the SQL name of the column
01228    * @return the column value
01229    * @exception SQLException if a database access error occurs
01230    */
01231   public String getString(String columnName) throws SQLException
01232   {
01233     return this.getString(findColumn(columnName));
01234   }
01235 
01236   /**
01237    * @see java.sql.ResultSet#getBoolean(java.lang.String)
01238    */
01239   public boolean getBoolean(String columnName) throws SQLException
01240   {
01241     return getBoolean(findColumn(columnName));
01242   }
01243 
01244   /**
01245    * @see java.sql.ResultSet#getByte(java.lang.String)
01246    */
01247   public byte getByte(String columnName) throws SQLException
01248   {
01249     return getByte(findColumn(columnName));
01250   }
01251 
01252   /**
01253    * @see java.sql.ResultSet#getShort(java.lang.String)
01254    */
01255   public short getShort(String columnName) throws SQLException
01256   {
01257     return getShort(findColumn(columnName));
01258   }
01259 
01260   /**
01261    * @see java.sql.ResultSet#getInt(java.lang.String)
01262    */
01263   public int getInt(String columnName) throws SQLException
01264   {
01265     return getInt(findColumn(columnName));
01266   }
01267 
01268   /**
01269    * @see java.sql.ResultSet#getLong(java.lang.String)
01270    */
01271   public long getLong(String columnName) throws SQLException
01272   {
01273     return getLong(findColumn(columnName));
01274   }
01275 
01276   /**
01277    * @see java.sql.ResultSet#getFloat(java.lang.String)
01278    */
01279   public float getFloat(String columnName) throws SQLException
01280   {
01281     return getFloat(findColumn(columnName));
01282   }
01283 
01284   /**
01285    * @see java.sql.ResultSet#getDouble(java.lang.String)
01286    */
01287   public double getDouble(String columnName) throws SQLException
01288   {
01289     return getDouble(findColumn(columnName));
01290   }
01291 
01292   /**
01293    * @see java.sql.ResultSet#getBigDecimal(String, int)
01294    * @deprecated
01295    */
01296   public BigDecimal getBigDecimal(String columnName, int scale)
01297       throws SQLException
01298   {
01299     return getBigDecimal(findColumn(columnName), scale);
01300   }
01301 
01302   /**
01303    * @see java.sql.ResultSet#getBytes(java.lang.String)
01304    */
01305   public byte[] getBytes(String columnName) throws SQLException
01306   {
01307     return getBytes(findColumn(columnName));
01308   }
01309 
01310   /**
01311    * @see java.sql.ResultSet#getDate(java.lang.String)
01312    */
01313   public java.sql.Date getDate(String columnName) throws SQLException
01314   {
01315     return getDate(findColumn(columnName));
01316   }
01317 
01318   /**
01319    * @see java.sql.ResultSet#getTime(java.lang.String)
01320    */
01321   public Time getTime(String columnName) throws SQLException
01322   {
01323     return getTime(findColumn(columnName));
01324   }
01325 
01326   /**
01327    * @see java.sql.ResultSet#getTimestamp(java.lang.String)
01328    */
01329   public Timestamp getTimestamp(String columnName) throws SQLException
01330   {
01331     return getTimestamp(findColumn(columnName));
01332   }
01333 
01334   /**
01335    * @see java.sql.ResultSet#getAsciiStream(java.lang.String)
01336    */
01337   public InputStream getAsciiStream(String columnName) throws SQLException
01338   {
01339     return getAsciiStream(findColumn(columnName));
01340   }
01341 
01342   /**
01343    * @see java.sql.ResultSet#getUnicodeStream(String)
01344    * @deprecated
01345    */
01346   public InputStream getUnicodeStream(String columnName) throws SQLException
01347   {
01348     return getUnicodeStream(findColumn(columnName));
01349   }
01350 
01351   /**
01352    * @see java.sql.ResultSet#getBinaryStream(java.lang.String)
01353    */
01354   public InputStream getBinaryStream(String columnName) throws SQLException
01355   {
01356     return getBinaryStream(findColumn(columnName));
01357   }
01358 
01359   /**
01360    * The first warning reported by calls on this ResultSet is returned.
01361    * Subsequent ResultSet warnings will be chained to this java.sql.SQLWarning.
01362    * <p>
01363    * The warning chain is automatically cleared each time a new row is read.
01364    * <p>
01365    * <B>Note: </B> This warning chain only covers warnings caused by ResultSet
01366    * methods. Any warnings caused by statement methods (such as reading OUT
01367    * parameters) will be chained on the Statement object.
01368    * 
01369    * @return the first java.sql.SQLWarning or null;
01370    * @exception SQLException if a database access error occurs.
01371    */
01372   public java.sql.SQLWarning getWarnings() throws SQLException
01373   {
01374     return warnings;
01375   }
01376 
01377   /**
01378    * After this call, getWarnings returns null until a new warning is reported
01379    * for this ResultSet
01380    * 
01381    * @exception SQLException if a database access error occurs
01382    */
01383 
01384   public void clearWarnings() throws SQLException
01385   {
01386     warnings = null;
01387   }
01388 
01389   /**
01390    * Get the name of the SQL cursor used by this ResultSet
01391    * <p>
01392    * In SQL, a result table is retrieved though a cursor that is named. The
01393    * current row of a result can be updated or deleted using a positioned
01394    * update/delete statement that references the cursor name.
01395    * <p>
01396    * JDBC supports this SQL feature by providing the name of the SQL cursor used
01397    * by a ResultSet. The current row of a ResulSet is also the current row of
01398    * this SQL cursor.
01399    * <p>
01400    * <B>Note: </B> If positioned update is not supported, a
01401    * java.sql.SQLException is thrown.
01402    * 
01403    * @return the ResultSet's SQL cursor name.
01404    * @exception SQLException if a database access error occurs
01405    */
01406   public String getCursorName() throws SQLException
01407   {
01408     throw new NotImplementedException("getCursorName()");
01409   }
01410 
01411   /**
01412    * Get the value of a column in the current row as a Java object
01413    * <p>
01414    * This method will return the value of the given column as a Java object. The
01415    * type of the Java object will be the default Java Object type corresponding
01416    * to the column's SQL type, following the mapping specified in the JDBC
01417    * specification.
01418    * <p>
01419    * This method may also be used to read database specific abstract data types.
01420    * 
01421    * @param columnIndex the first column is 1, the second is 2...
01422    * @return a Object holding the column value
01423    * @exception SQLException if a database access error occurs
01424    */
01425   public Object getObject(int columnIndex) throws SQLException
01426   {
01427     checkRowAndColPosAndSetNullFlag(columnIndex);
01428 
01429     if (wasNullFlag)
01430       return null;
01431 
01432     Object o;
01433     if (inserting || updating)
01434       o = tempRow[columnIndex];
01435     else
01436       o = ((Object[]) data.get(currentRow))[columnIndex - 1];
01437 
01438     if (o instanceof byte[])
01439     {
01440       try
01441       {
01442         byte[] b = owningStatement.connection.getBlobFilter()
01443             .decode((byte[]) o);
01444         return new ObjectInputStream(new ByteArrayInputStream(b)).readObject();
01445       }
01446       catch (ClassNotFoundException e)
01447       {
01448         e.printStackTrace();
01449         throw new SQLException("Missing class while deserializing Blob" + e);
01450       }
01451       catch (IOException e)
01452       {
01453         e.printStackTrace();
01454         throw new SQLException("IOException while deserializing Blob" + e);
01455       }
01456     }
01457     else
01458     {
01459       return o;
01460     }
01461   }
01462 
01463   /**
01464    * Get the value of a column in the current row as a Java object
01465    * <p>
01466    * This method will return the value of the given column as a Java object. The
01467    * type of the Java object will be the default Java Object type corresponding
01468    * to the column's SQL type, following the mapping specified in the JDBC
01469    * specification.
01470    * <p>
01471    * This method may also be used to read database specific abstract data types.
01472    * 
01473    * @param columnName is the SQL name of the column
01474    * @return a Object holding the column value
01475    * @exception SQLException if a database access error occurs
01476    */
01477   public Object getObject(String columnName) throws SQLException
01478   {
01479     return getObject(findColumn(columnName));
01480   }
01481 
01482   //--------------------------JDBC 2.0-----------------------------------
01483 
01484   /**
01485    * @see java.sql.ResultSet#getCharacterStream(int)
01486    */
01487   public java.io.Reader getCharacterStream(int columnIndex) throws SQLException
01488   {
01489     String s = getString(columnIndex);
01490     if (s == null)
01491       return null;
01492     char[] data = s.toCharArray();
01493     return new java.io.CharArrayReader(data);
01494   }
01495 
01496   /**
01497    * @see java.sql.ResultSet#getCharacterStream(java.lang.String)
01498    */
01499   public java.io.Reader getCharacterStream(String columnName)
01500       throws SQLException
01501   {
01502     return getCharacterStream(findColumn(columnName));
01503   }
01504 
01505   /**
01506    * JDBC 2.0 Get the value of a column in the current row as a
01507    * java.math.BigDecimal object.
01508    * 
01509    * @param columnIndex the first column is 1, the second is 2, ...
01510    * @return the column value (full precision); if the value is SQL NULL, the
01511    *         result is null
01512    * @exception SQLException if a database-access error occurs.
01513    */
01514   public BigDecimal getBigDecimal(int columnIndex) throws SQLException
01515   {
01516     checkRowAndColPosAndSetNullFlag(columnIndex);
01517 
01518     if (wasNullFlag)
01519       return null;
01520 
01521     Object obj;
01522     if (inserting || updating)
01523       obj = tempRow[columnIndex - 1];
01524     else
01525       obj = ((Object[]) data.get(currentRow))[columnIndex - 1];
01526 
01527     if (obj instanceof BigDecimal)
01528       return (BigDecimal) obj;
01529     else if (obj instanceof Long)
01530     {
01531       return new BigDecimal(((Long) obj).longValue());
01532     }
01533     else if (obj instanceof BigInteger)
01534     {
01535       return new BigDecimal(((BigInteger) obj));
01536     }
01537     else if (obj instanceof Short)
01538     {
01539       return new BigDecimal(((Short) obj).shortValue());
01540     }
01541     else if (obj instanceof Integer)
01542     {
01543       return new BigDecimal(((Integer) obj).intValue());
01544     }
01545     else if (obj instanceof String)
01546     {
01547       return new BigDecimal((String) obj);
01548     }
01549     else if (obj instanceof Number)
01550     {
01551       // float and double have to be converted via string
01552       // othwerwise we produce errors
01553       // javadoc for BigDecimal :
01554       // Note: the results of this constructor can be somewhat unpredictable.
01555       // One might assume that new BigDecimal(.1) is exactly equal to .1, but
01556       // it is actually equal to
01557       // .1000000000000000055511151231257827021181583404541015625. This is so
01558       // because .1 cannot be represented exactly as a double (or, for that
01559       // matter, as a binary fraction of any finite length). Thus, the long
01560       // value that is being passed in to the constructor is not exactly equal
01561       // to .1, appearances nonwithstanding.
01562 
01563       // The (String) constructor, on the other hand, is perfectly
01564       // predictable: new BigDecimal(".1") is exactly equal to .1, as one
01565       // would expect. Therefore, it is generally recommended that the
01566       // (String) constructor be used in preference to this one.
01567       return new BigDecimal(obj.toString());
01568     }
01569     else
01570     {
01571       throw new SQLException("Type " + obj.getClass().getName()
01572           + " is not compatible with BigDecimal");
01573     }
01574   }
01575 
01576   /**
01577    * @see java.sql.ResultSet#getBigDecimal(java.lang.String)
01578    */
01579   public BigDecimal getBigDecimal(String columnName) throws SQLException
01580   {
01581     return getBigDecimal(findColumn(columnName));
01582   }
01583 
01584   /**
01585    * JDBC 2.0 Returns the value of column as a Java object. Use the map to
01586    * determine the class from which to construct data of SQL structured and
01587    * distinct types.
01588    * 
01589    * @param i the first column is 1, the second is 2, ...
01590    * @param map the mapping from SQL type names to Java classes
01591    * @return an object representing the SQL value
01592    * @exception SQLException if a database-access error occurs.
01593    */
01594   public Object getObject(int i, java.util.Map map) throws SQLException
01595   {
01596     throw new NotImplementedException("getObject(int, java.util.Map)");
01597   }
01598 
01599   /**
01600    * JDBC 2.0 Get a REF(&lt;structured-type&gt;) column.
01601    * 
01602    * @param i the first column is 1, the second is 2, ...
01603    * @return an object representing data of an SQL REF type
01604    * @exception SQLException if a database-access error occurs.
01605    */
01606   public java.sql.Ref getRef(int i) throws SQLException
01607   {
01608     throw new NotImplementedException("getRef");
01609   }
01610 
01611   /**
01612    * JDBC 2.0 Gets a BLOB column.
01613    * 
01614    * @param columnIndex the first column is 1, the second is 2, ...
01615    * @return an object representing a BLOB
01616    * @exception SQLException if a database-access error occurs.
01617    */
01618   public java.sql.Blob getBlob(int columnIndex) throws SQLException
01619   {
01620     checkRowAndColPosAndSetNullFlag(columnIndex);
01621 
01622     if (wasNullFlag)
01623       return null;
01624 
01625     Object o;
01626     if (inserting || updating)
01627       o = tempRow[columnIndex - 1];
01628     else
01629       o = (((Object[]) data.get(currentRow))[columnIndex - 1]);
01630 
01631     // Test if the type of the Blob is indeed a Blob else we assume these are
01632     // just bytes.
01633     if (o instanceof Blob)
01634       return (java.sql.Blob) o;
01635     else
01636       return new Blob(getBytes(columnIndex));
01637   }
01638 
01639   /**
01640    * JDBC 2.0 Gets a CLOB column.
01641    * 
01642    * @param columnIndex the first column is 1, the second is 2, ...
01643    * @return an object representing a CLOB
01644    * @exception SQLException if a database-access error occurs.
01645    */
01646   public java.sql.Clob getClob(int columnIndex) throws SQLException
01647   {
01648     checkRowAndColPosAndSetNullFlag(columnIndex);
01649 
01650     if (wasNullFlag)
01651       return null;
01652 
01653     Object o;
01654     if (inserting || updating)
01655       o = tempRow[columnIndex - 1];
01656     else
01657       o = (((Object[]) data.get(currentRow))[columnIndex - 1]);
01658 
01659     // Test if the type of the Clob is indeed a Clob or just a String
01660     //throw new SQLException("Class:"+o.getClass());
01661     if (o instanceof String)
01662       return new Clob((String) o);
01663     else if (o instanceof Clob)
01664       return (java.sql.Clob) o;
01665     else
01666       return new Clob(new String(o.toString()));
01667   }
01668 
01669   /**
01670    * JDBC 2.0 Gets an array column.
01671    * 
01672    * @param columnIndex the first column is 1, the second is 2, ...
01673    * @return an object representing an SQL array
01674    * @exception SQLException if a database-access error occurs.
01675    */
01676   public java.sql.Array getArray(int columnIndex) throws SQLException
01677   {
01678     checkRowAndColPosAndSetNullFlag(columnIndex);
01679 
01680     if (wasNullFlag)
01681       return null;
01682 
01683     if (inserting || updating)
01684       return (java.sql.Array) tempRow[columnIndex - 1];
01685     else
01686       return (java.sql.Array) (((Object[]) data.get(currentRow))[columnIndex - 1]);
01687   }
01688 
01689   /**
01690    * JDBC 2.0 Returns the value of column as a Java object. Use the map to
01691    * determine the class from which to construct data of SQL structured and
01692    * distinct types.
01693    * 
01694    * @param colName the column name
01695    * @param map the mapping from SQL type names to Java classes
01696    * @return an object representing the SQL value
01697    * @exception SQLException if a database-access error occurs.
01698    */
01699   public Object getObject(String colName, java.util.Map map)
01700       throws SQLException
01701   {
01702     throw new NotImplementedException("getObject(String, java.util.Map)");
01703   }
01704 
01705   /**
01706    * JDBC 2.0 Get a REF(&lt;structured-type&gt;) column.
01707    * 
01708    * @param colName the column name
01709    * @return an object representing data of an SQL REF type
01710    * @exception SQLException if a database-access error occurs.
01711    */
01712   public java.sql.Ref getRef(String colName) throws SQLException
01713   {
01714     throw new NotImplementedException("getRef(String)");
01715   }
01716 
01717   /**
01718    * JDBC 2.0 Get a BLOB column.
01719    * 
01720    * @param colName the column name
01721    * @return an object representing a BLOB
01722    * @exception SQLException if a database-access error occurs.
01723    */
01724   public java.sql.Blob getBlob(String colName) throws SQLException
01725   {
01726     return getBlob(findColumn(colName));
01727   }
01728 
01729   /**
01730    * JDBC 2.0 Get a CLOB column.
01731    * 
01732    * @param colName the column name
01733    * @return an object representing a CLOB
01734    * @exception SQLException if a database-access error occurs.
01735    */
01736   public java.sql.Clob getClob(String colName) throws SQLException
01737   {
01738     return getClob(findColumn(colName));
01739   }
01740 
01741   /**
01742    * JDBC 2.0 Get an array column.
01743    * 
01744    * @param colName the column name
01745    * @return an object representing an SQL array
01746    * @exception SQLException if a database-access error occurs.
01747    */
01748   public java.sql.Array getArray(String colName) throws SQLException
01749   {
01750     return getArray(findColumn(colName));
01751   }
01752 
01753   /**
01754    * JDBC 2.0 Get the value of a column in the current row as a java.sql.Date
01755    * object. Use the calendar to construct an appropriate millisecond value for
01756    * the Date, if the underlying database doesn't store timezone information.
01757    * 
01758    * @param columnIndex the first column is 1, the second is 2, ...
01759    * @param cal the calendar to use in constructing the date
01760    * @return the column value; if the value is SQL NULL, the result is null
01761    * @exception SQLException if a database-access error occurs.
01762    */
01763   public java.sql.Date getDate(int columnIndex, Calendar cal)
01764       throws SQLException
01765   {
01766     throw new NotImplementedException("getDate(int, Calendar)");
01767   }
01768 
01769   /**
01770    * Get the value of a column in the current row as a java.sql.Date object. Use
01771    * the calendar to construct an appropriate millisecond value for the Date, if
01772    * the underlying database doesn't store timezone information.
01773    * 
01774    * @param columnName is the SQL name of the column
01775    * @param cal the calendar to use in constructing the date
01776    * @return the column value; if the value is SQL NULL, the result is null
01777    * @exception SQLException if a database-access error occurs.
01778    */
01779   public java.sql.Date getDate(String columnName, Calendar cal)
01780       throws SQLException
01781   {
01782     throw new NotImplementedException("getDate(String, Calendar)");
01783   }
01784 
01785   /**
01786    * Get the value of a column in the current row as a java.sql.Time object. Use
01787    * the calendar to construct an appropriate millisecond value for the Time, if
01788    * the underlying database doesn't store timezone information.
01789    * 
01790    * @param columnIndex the first column is 1, the second is 2, ...
01791    * @param cal the calendar to use in constructing the time
01792    * @return the column value; if the value is SQL NULL, the result is null
01793    * @exception SQLException if a database-access error occurs.
01794    */
01795   public java.sql.Time getTime(int columnIndex, Calendar cal)
01796       throws SQLException
01797   {
01798     throw new NotImplementedException("getTime(int, Calendar)");
01799   }
01800 
01801   /**
01802    * Get the value of a column in the current row as a java.sql.Time object. Use
01803    * the calendar to construct an appropriate millisecond value for the Time, if
01804    * the underlying database doesn't store timezone information.
01805    * 
01806    * @param columnName is the SQL name of the column
01807    * @param cal the calendar to use in constructing the time
01808    * @return the column value; if the value is SQL NULL, the result is null
01809    * @exception SQLException if a database-access error occurs.
01810    */
01811   public java.sql.Time getTime(String columnName, Calendar cal)
01812       throws SQLException
01813   {
01814     throw new NotImplementedException("getTime(String, Calendar)");
01815   }
01816 
01817   /**
01818    * Get the value of a column in the current row as a java.sql.Timestamp
01819    * object. Use the calendar to construct an appropriate millisecond value for
01820    * the Timestamp, if the underlying database doesn't store timezone
01821    * information.
01822    * 
01823    * @param columnIndex the first column is 1, the second is 2, ...
01824    * @param cal the calendar to use in constructing the timestamp
01825    * @return the column value; if the value is SQL NULL, the result is null
01826    * @exception SQLException if a database-access error occurs.
01827    */
01828   public java.sql.Timestamp getTimestamp(int columnIndex, Calendar cal)
01829       throws SQLException
01830   {
01831     throw new NotImplementedException("getTimestamp(int, Calendar)");
01832   }
01833 
01834   /**
01835    * Get the value of a column in the current row as a java.sql.Timestamp
01836    * object. Use the calendar to construct an appropriate millisecond value for
01837    * the Timestamp, if the underlying database doesn't store timezone
01838    * information.
01839    * 
01840    * @param columnName is the SQL name of the column
01841    * @param cal the calendar to use in constructing the timestamp
01842    * @return the column value; if the value is SQL NULL, the result is null
01843    * @exception SQLException if a database-access error occurs.
01844    */
01845   public java.sql.Timestamp getTimestamp(String columnName, Calendar cal)
01846       throws SQLException
01847   {
01848     throw new NotImplementedException("getTimestamp(String, Calendar)");
01849   }
01850 
01851   //---------------------------------------------------------------------
01852   // Updates
01853   //---------------------------------------------------------------------
01854 
01855   /**
01856    * JDBC 2.0 Determine if the current row has been updated. The value returned
01857    * depends on whether or not the result set can detect updates.
01858    * 
01859    * @return <code>true</code> if the row has been visibly updated by the
01860    *         owner or another, and updates are detected
01861    * @exception SQLException if a database-access error occurs
01862    * @see DatabaseMetaData#updatesAreDetected
01863    */
01864   public boolean rowUpdated() throws SQLException
01865   {
01866     throw new NotImplementedException("rowUpdated");
01867   }
01868 
01869   /**
01870    * JDBC 2.0 Determine if the current row has been inserted. The value returned
01871    * depends on whether or not the result set can detect visible inserts.
01872    * 
01873    * @return <code>true</code> if inserted and inserts are detected
01874    * @exception SQLException if a database-access error occurs
01875    * @see DatabaseMetaData#insertsAreDetected
01876    */
01877   public boolean rowInserted() throws SQLException
01878   {
01879     throw new NotImplementedException("rowInserted");
01880   }
01881 
01882   /**
01883    * JDBC 2.0 Determine if this row has been deleted. A deleted row may leave a
01884    * visible "hole" in a result set. This method can be used to detect holes in
01885    * a result set. The value returned depends on whether or not the result set
01886    * can detect deletions.
01887    * 
01888    * @return <code>true</code> if deleted and deletes are detected
01889    * @exception SQLException if a database-access error occurs
01890    * @see DatabaseMetaData#deletesAreDetected
01891    */
01892   public boolean rowDeleted() throws SQLException
01893   {
01894     throw new NotImplementedException("rowDeleted");
01895   }
01896 
01897   /**
01898    * JDBC 2.0 Give a nullable column a null value. The updateXXX() methods are
01899    * used to update column values in the current row, or the insert row. The
01900    * updateXXX() methods do not update the underlying database, instead the
01901    * updateRow() or insertRow() methods are called to update the database.
01902    * 
01903    * @param columnIndex the first column is 1, the second is 2, ...
01904    * @exception SQLException if a database-access error occurs
01905    */
01906   public void updateNull(int columnIndex) throws SQLException
01907   {
01908     checkIfClosed();
01909 
01910     if (inserting)
01911       insertStatement
01912           .setNull(columnIndex, fields[columnIndex - 1].getSqlType());
01913     else
01914     {
01915       checkUpdateFlagAndPrepareUpdateIfNeeded();
01916       updateStatement
01917           .setNull(columnIndex, fields[columnIndex - 1].getSqlType());
01918     }
01919 
01920     tempRow[columnIndex - 1] = null;
01921   }
01922 
01923   /**
01924    * JDBC 2.0 Update a column with a boolean value. The updateXXX() methods are
01925    * used to update column values in the current row, or the insert row. The
01926    * updateXXX() methods do not update the underlying database, instead the
01927    * updateRow() or insertRow() methods are called to update the database.
01928    * 
01929    * @param columnIndex the first column is 1, the second is 2, ...
01930    * @param x the new column value
01931    * @exception SQLException if a database-access error occurs
01932    */
01933 
01934   public void updateBoolean(int columnIndex, boolean x) throws SQLException
01935   {
01936     checkIfClosed();
01937 
01938     if (inserting)
01939       insertStatement.setBoolean(columnIndex, x);
01940     else
01941     {
01942       checkUpdateFlagAndPrepareUpdateIfNeeded();
01943       updateStatement.setBoolean(columnIndex, x);
01944     }
01945 
01946     tempRow[columnIndex - 1] = Boolean.valueOf(x);
01947   }
01948 
01949   /**
01950    * JDBC 2.0 Update a column with a byte value. The updateXXX() methods are
01951    * used to update column values in the current row, or the insert row. The
01952    * updateXXX() methods do not update the underlying database, instead the
01953    * updateRow() or insertRow() methods are called to update the database.
01954    * 
01955    * @param columnIndex the first column is 1, the second is 2, ...
01956    * @param x the new column value
01957    * @exception SQLException if a database-access error occurs
01958    */
01959   public void updateByte(int columnIndex, byte x) throws SQLException
01960   {
01961     checkIfClosed();
01962 
01963     if (inserting)
01964       insertStatement.setByte(columnIndex, x);
01965     else
01966     {
01967       checkUpdateFlagAndPrepareUpdateIfNeeded();
01968       updateStatement.setByte(columnIndex, x);
01969     }
01970 
01971     tempRow[columnIndex - 1] = new Byte(x);
01972   }
01973 
01974   /**
01975    * JDBC 2.0 Update a column with a short value. The updateXXX() methods are
01976    * used to update column values in the current row, or the insert row. The
01977    * updateXXX() methods do not update the underlying database, instead the
01978    * updateRow() or insertRow() methods are called to update the database.
01979    * 
01980    * @param columnIndex the first column is 1, the second is 2, ...
01981    * @param x the new column value
01982    * @exception SQLException if a database-access error occurs
01983    */
01984   public void updateShort(int columnIndex, short x) throws SQLException
01985   {
01986     checkIfClosed();
01987 
01988     if (inserting)
01989       insertStatement.setShort(columnIndex, x);
01990     else
01991     {
01992       checkUpdateFlagAndPrepareUpdateIfNeeded();
01993       updateStatement.setShort(columnIndex, x);
01994     }
01995 
01996     tempRow[columnIndex - 1] = new Short(x);
01997   }
01998 
01999   /**
02000    * JDBC 2.0 Update a column with an integer value. The updateXXX() methods are
02001    * used to update column values in the current row, or the insert row. The
02002    * updateXXX() methods do not update the underlying database, instead the
02003    * updateRow() or insertRow() methods are called to update the database.
02004    * 
02005    * @param columnIndex the first column is 1, the second is 2, ...
02006    * @param x the new column value
02007    * @exception SQLException if a database-access error occurs
02008    */
02009   public void updateInt(int columnIndex, int x) throws SQLException
02010   {
02011     checkIfClosed();
02012 
02013     if (inserting)
02014       insertStatement.setInt(columnIndex, x);
02015     else
02016     {
02017       checkUpdateFlagAndPrepareUpdateIfNeeded();
02018       updateStatement.setInt(columnIndex, x);
02019     }
02020 
02021     tempRow[columnIndex - 1] = new Integer(x);
02022   }
02023 
02024   /**
02025    * JDBC 2.0 Update a column with a long value. The updateXXX() methods are
02026    * used to update column values in the current row, or the insert row. The
02027    * updateXXX() methods do not update the underlying database, instead the
02028    * updateRow() or insertRow() methods are called to update the database.
02029    * 
02030    * @param columnIndex the first column is 1, the second is 2, ...
02031    * @param x the new column value
02032    * @exception SQLException if a database-access error occurs
02033    */
02034   public void updateLong(int columnIndex, long x) throws SQLException
02035   {
02036     checkIfClosed();
02037 
02038     if (inserting)
02039       insertStatement.setLong(columnIndex, x);
02040     else
02041     {
02042       checkUpdateFlagAndPrepareUpdateIfNeeded();
02043       updateStatement.setLong(columnIndex, x);
02044     }
02045 
02046     tempRow[columnIndex - 1] = new Long(x);
02047   }
02048 
02049   /**
02050    * JDBC 2.0 Update a column with a float value. The updateXXX() methods are
02051    * used to update column values in the current row, or the insert row. The
02052    * updateXXX() methods do not update the underlying database, instead the
02053    * updateRow() or insertRow() methods are called to update the database.
02054    * 
02055    * @param columnIndex the first column is 1, the second is 2, ...
02056    * @param x the new column value
02057    * @exception SQLException if a database-access error occurs
02058    */
02059   public void updateFloat(int columnIndex, float x) throws SQLException
02060   {
02061     checkIfClosed();
02062 
02063     if (inserting)
02064       insertStatement.setFloat(columnIndex, x);
02065     else
02066     {
02067       checkUpdateFlagAndPrepareUpdateIfNeeded();
02068       updateStatement.setFloat(columnIndex, x);
02069     }
02070 
02071     tempRow[columnIndex - 1] = new Float(x);
02072   }
02073 
02074   /**
02075    * JDBC 2.0 Update a column with a Double value. The updateXXX() methods are
02076    * used to update column values in the current row, or the insert row. The
02077    * updateXXX() methods do not update the underlying database, instead the
02078    * updateRow() or insertRow() methods are called to update the database.
02079    * 
02080    * @param columnIndex the first column is 1, the second is 2, ...
02081    * @param x the new column value
02082    * @exception SQLException if a database-access error occurs
02083    */
02084   public void updateDouble(int columnIndex, double x) throws SQLException
02085   {
02086     checkIfClosed();
02087 
02088     if (inserting)
02089       insertStatement.setDouble(columnIndex, x);
02090     else
02091     {
02092       checkUpdateFlagAndPrepareUpdateIfNeeded();
02093       updateStatement.setDouble(columnIndex, x);
02094     }
02095 
02096     tempRow[columnIndex - 1] = new Double(x);
02097   }
02098 
02099   /**
02100    * JDBC 2.0 Update a column with a BigDecimal value. The updateXXX() methods
02101    * are used to update column values in the current row, or the insert row. The
02102    * updateXXX() methods do not update the underlying database, instead the
02103    * updateRow() or insertRow() methods are called to update the database.
02104    * 
02105    * @param columnIndex the first column is 1, the second is 2, ...
02106    * @param x the new column value
02107    * @exception SQLException if a database-access error occurs
02108    */
02109   public void updateBigDecimal(int columnIndex, BigDecimal x)
02110       throws SQLException
02111   {
02112     checkIfClosed();
02113 
02114     if (inserting)
02115       insertStatement.setBigDecimal(columnIndex, x);
02116     else
02117     {
02118       checkUpdateFlagAndPrepareUpdateIfNeeded();
02119       updateStatement.setBigDecimal(columnIndex, x);
02120     }
02121 
02122     tempRow[columnIndex - 1] = x;
02123   }
02124 
02125   /**
02126    * JDBC 2.0 Update a column with a String value. The updateXXX() methods are
02127    * used to update column values in the current row, or the insert row. The
02128    * updateXXX() methods do not update the underlying database, instead the
02129    * updateRow() or insertRow() methods are called to update the database.
02130    * 
02131    * @param columnIndex the first column is 1, the second is 2, ...
02132    * @param x the new column value
02133    * @exception SQLException if a database-access error occurs
02134    */
02135   public void updateString(int columnIndex, String x) throws SQLException
02136   {
02137     checkIfClosed();
02138 
02139     if (inserting)
02140       insertStatement.setString(columnIndex, x);
02141     else
02142     {
02143       checkUpdateFlagAndPrepareUpdateIfNeeded();
02144       updateStatement.setString(columnIndex, x);
02145     }
02146 
02147     tempRow[columnIndex - 1] = x;
02148   }
02149 
02150   /**
02151    * JDBC 2.0 Update a column with a byte array value. The updateXXX() methods
02152    * are used to update column values in the current row, or the insert row. The
02153    * updateXXX() methods do not update the underlying database, instead the
02154    * updateRow() or insertRow() methods are called to update the database.
02155    * 
02156    * @param columnIndex the first column is 1, the second is 2, ...
02157    * @param x the new column value
02158    * @exception SQLException if a database-access error occurs
02159    */
02160   public void updateBytes(int columnIndex, byte x[]) throws SQLException
02161   {
02162     checkIfClosed();
02163 
02164     if (inserting)
02165       insertStatement.setBytes(columnIndex, x);
02166     else
02167     {
02168       checkUpdateFlagAndPrepareUpdateIfNeeded();
02169       updateStatement.setBytes(columnIndex, x);
02170     }
02171 
02172     tempRow[columnIndex - 1] = x;
02173   }
02174 
02175   /**
02176    * JDBC 2.0 Update a column with a Date value. The updateXXX() methods are
02177    * used to update column values in the current row, or the insert row. The
02178    * updateXXX() methods do not update the underlying database, instead the
02179    * updateRow() or insertRow() methods are called to update the database.
02180    * 
02181    * @param columnIndex the first column is 1, the second is 2, ...
02182    * @param x the new column value
02183    * @exception SQLException if a database-access error occurs
02184    */
02185   public void updateDate(int columnIndex, java.sql.Date x) throws SQLException
02186   {
02187     checkIfClosed();
02188 
02189     if (inserting)
02190       insertStatement.setDate(columnIndex, x);
02191     else
02192     {
02193       checkUpdateFlagAndPrepareUpdateIfNeeded();
02194       updateStatement.setDate(columnIndex, x);
02195     }
02196 
02197     tempRow[columnIndex - 1] = x;
02198   }
02199 
02200   /**
02201    * JDBC 2.0 Update a column with a Time value. The updateXXX() methods are
02202    * used to update column values in the current row, or the insert row. The
02203    * updateXXX() methods do not update the underlying database, instead the
02204    * updateRow() or insertRow() methods are called to update the database.
02205    * 
02206    * @param columnIndex the first column is 1, the second is 2, ...
02207    * @param x the new column value
02208    * @exception SQLException if a database-access error occurs
02209    */
02210   public void updateTime(int columnIndex, java.sql.Time x) throws SQLException
02211   {
02212     checkIfClosed();
02213 
02214     if (inserting)
02215       insertStatement.setTime(columnIndex, x);
02216     else
02217     {
02218       checkUpdateFlagAndPrepareUpdateIfNeeded();
02219       updateStatement.setTime(columnIndex, x);
02220     }
02221 
02222     tempRow[columnIndex - 1] = x;
02223   }
02224 
02225   /**
02226    * JDBC 2.0 Update a column with a Timestamp value. The updateXXX() methods
02227    * are used to update column values in the current row, or the insert row. The
02228    * updateXXX() methods do not update the underlying database, instead the
02229    * updateRow() or insertRow() methods are called to update the database.
02230    * 
02231    * @param columnIndex the first column is 1, the second is 2, ...
02232    * @param x the new column value
02233    * @exception SQLException if a database-access error occurs
02234    */
02235   public void updateTimestamp(int columnIndex, java.sql.Timestamp x)
02236       throws SQLException
02237   {
02238     checkIfClosed();
02239 
02240     if (inserting)
02241       insertStatement.setTimestamp(columnIndex, x);
02242     else
02243     {
02244       checkUpdateFlagAndPrepareUpdateIfNeeded();
02245       updateStatement.setTimestamp(columnIndex, x);
02246     }
02247 
02248     tempRow[columnIndex - 1] = x;
02249   }
02250 
02251   /**
02252    * JDBC 2.0 Update a column with an ascii stream value. The updateXXX()
02253    * methods are used to update column values in the current row, or the insert
02254    * row. The updateXXX() methods do not update the underlying database, instead
02255    * the updateRow() or insertRow() methods are called to update the database.
02256    * 
02257    * @param columnIndex the first column is 1, the second is 2, ...
02258    * @param x the new column value
02259    * @param length the length of the stream
02260    * @exception SQLException if a database-access error occurs
02261    */
02262   public void updateAsciiStream(int columnIndex, java.io.InputStream x,
02263       int length) throws SQLException
02264   {
02265     this.updateBinaryStream(columnIndex, x, length);
02266   }
02267 
02268   /**
02269    * JDBC 2.0 Update a column with a binary stream value. The updateXXX()
02270    * methods are used to update column values in the current row, or the insert
02271    * row. The updateXXX() methods do not update the underlying database, instead
02272    * the updateRow() or insertRow() methods are called to update the database.
02273    * 
02274    * @param columnIndex the first column is 1, the second is 2, ...
02275    * @param x the new column value
02276    * @param length the length of the stream
02277    * @exception SQLException if a database-access error occurs
02278    */
02279   public void updateBinaryStream(int columnIndex, java.io.InputStream x,
02280       int length) throws SQLException
02281   {
02282     checkIfClosed();
02283 
02284     byte[] data = new byte[length];
02285     try
02286     {
02287       x.read(data, 0, length);
02288     }
02289     catch (Exception ioe)
02290     {
02291       throw new SQLException("Problem with streaming of data");
02292     }
02293 
02294     this.updateBytes(columnIndex, data);
02295   }
02296 
02297   /**
02298    * JDBC 2.0 Update a column with a character stream value. The updateXXX()
02299    * methods are used to update column values in the current row, or the insert
02300    * row. The updateXXX() methods do not update the underlying database, instead
02301    * the updateRow() or insertRow() methods are called to update the database.
02302    * 
02303    * @param columnIndex the first column is 1, the second is 2, ...
02304    * @param x the new column value
02305    * @param length the length of the stream
02306    * @exception SQLException if a database-access error occurs
02307    */
02308   public void updateCharacterStream(int columnIndex, java.io.Reader x,
02309       int length) throws SQLException
02310   {
02311     checkIfClosed();
02312 
02313     char[] data = new char[length];
02314     try
02315     {
02316       x.read(data, 0, length);
02317     }
02318     catch (Exception ioe)
02319     {
02320       throw new SQLException("Problem with streaming of data");
02321     }
02322 
02323     this.updateString(columnIndex, new String(data));
02324   }
02325 
02326   /**
02327    * JDBC 2.0 Update a column with an Object value. The updateXXX() methods are
02328    * used to update column values in the current row, or the insert row. The
02329    * updateXXX() methods do not update the underlying database, instead the
02330    * updateRow() or insertRow() methods are called to update the database.
02331    * 
02332    * @param columnIndex the first column is 1, the second is 2, ...
02333    * @param x the new column value
02334    * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
02335    *          this is the number of digits after the decimal. For all other
02336    *          types this value will be ignored.
02337    * @exception SQLException if a database-access error occurs
02338    */
02339   public void updateObject(int columnIndex, Object x, int scale)
02340       throws SQLException
02341   {
02342     checkIfClosed();
02343 
02344     if (inserting)
02345       insertStatement.setObject(columnIndex, x, scale);
02346     else
02347     {
02348       checkUpdateFlagAndPrepareUpdateIfNeeded();
02349       updateStatement.setObject(columnIndex, x, scale);
02350     }
02351 
02352     tempRow[columnIndex - 1] = x;
02353   }
02354 
02355   /**
02356    * JDBC 2.0 Update a column with an Object value. The updateXXX() methods are
02357    * used to update column values in the current row, or the insert row. The
02358    * updateXXX() methods do not update the underlying database, instead the
02359    * updateRow() or insertRow() methods are called to update the database.
02360    * 
02361    * @param columnIndex the first column is 1, the second is 2, ...
02362    * @param x the new column value
02363    * @exception SQLException if a database-access error occurs
02364    */
02365   public void updateObject(int columnIndex, Object x) throws SQLException
02366   {
02367     checkIfClosed();
02368 
02369     if (inserting)
02370       insertStatement.setObject(columnIndex, x);
02371     else
02372     {
02373       checkUpdateFlagAndPrepareUpdateIfNeeded();
02374       updateStatement.setObject(columnIndex, x);
02375     }
02376 
02377     tempRow[columnIndex - 1] = x;
02378   }
02379 
02380   /**
02381    * JDBC 2.0 Update a column with a null value. The updateXXX() methods are
02382    * used to update column values in the current row, or the insert row. The
02383    * updateXXX() methods do not update the underlying database, instead the
02384    * updateRow() or insertRow() methods are called to update the database.
02385    * 
02386    * @param columnName the name of the column
02387    * @exception SQLException if a database-access error occurs
02388    */
02389 
02390   public void updateNull(String columnName) throws SQLException
02391   {
02392     this.updateNull(findColumn(columnName));
02393   }
02394 
02395   /**
02396    * JDBC 2.0 Update a column with a boolean value. The updateXXX() methods are
02397    * used to update column values in the current row, or the insert row. The
02398    * updateXXX() methods do not update the underlying database, instead the
02399    * updateRow() or insertRow() methods are called to update the database.
02400    * 
02401    * @param columnName the name of the column
02402    * @param x the new column value
02403    * @exception SQLException if a database-access error occurs
02404    */
02405   public void updateBoolean(String columnName, boolean x) throws SQLException
02406   {
02407     this.updateBoolean(findColumn(columnName), x);
02408   }
02409 
02410   /**
02411    * JDBC 2.0 Update a column with a byte value. The updateXXX() methods are
02412    * used to update column values in the current row, or the insert row. The
02413    * updateXXX() methods do not update the underlying database, instead the
02414    * updateRow() or insertRow() methods are called to update the database.
02415    * 
02416    * @param columnName the name of the column
02417    * @param x the new column value
02418    * @exception SQLException if a database-access error occurs
02419    */
02420   public void updateByte(String columnName, byte x) throws SQLException
02421   {
02422     this.updateByte(findColumn(columnName), x);
02423   }
02424 
02425   /**
02426    * JDBC 2.0 Update a column with a short value. The updateXXX() methods are
02427    * used to update column values in the current row, or the insert row. The
02428    * updateXXX() methods do not update the underlying database, instead the
02429    * updateRow() or insertRow() methods are called to update the database.
02430    * 
02431    * @param columnName the name of the column
02432    * @param x the new column value
02433    * @exception SQLException if a database-access error occurs
02434    */
02435   public void updateShort(String columnName, short x) throws SQLException
02436   {
02437     this.updateShort(findColumn(columnName), x);
02438   }
02439 
02440   /**
02441    * JDBC 2.0 Update a column with an integer value. The updateXXX() methods are
02442    * used to update column values in the current row, or the insert row. The
02443    * updateXXX() methods do not update the underlying database, instead the
02444    * updateRow() or insertRow() methods are called to update the database.
02445    * 
02446    * @param columnName the name of the column
02447    * @param x the new column value
02448    * @exception SQLException if a database-access error occurs
02449    */
02450   public void updateInt(String columnName, int x) throws SQLException
02451   {
02452     this.updateInt(findColumn(columnName), x);
02453   }
02454 
02455   /**
02456    * JDBC 2.0 Update a column with a long value. The updateXXX() methods are
02457    * used to update column values in the current row, or the insert row. The
02458    * updateXXX() methods do not update the underlying database, instead the
02459    * updateRow() or insertRow() methods are called to update the database.
02460    * 
02461    * @param columnName the name of the column
02462    * @param x the new column value
02463    * @exception SQLException if a database-access error occurs
02464    */
02465   public void updateLong(String columnName, long x) throws SQLException
02466   {
02467     this.updateLong(findColumn(columnName), x);
02468   }
02469 
02470   /**
02471    * JDBC 2.0 Update a column with a float value. The updateXXX() methods are
02472    * used to update column values in the current row, or the insert row. The
02473    * updateXXX() methods do not update the underlying database, instead the
02474    * updateRow() or insertRow() methods are called to update the database.
02475    * 
02476    * @param columnName the name of the column
02477    * @param x the new column value
02478    * @exception SQLException if a database-access error occurs
02479    */
02480   public void updateFloat(String columnName, float x) throws SQLException
02481   {
02482     this.updateFloat(findColumn(columnName), x);
02483   }
02484 
02485   /**
02486    * JDBC 2.0 Update a column with a double value. The updateXXX() methods are
02487    * used to update column values in the current row, or the insert row. The
02488    * updateXXX() methods do not update the underlying database, instead the
02489    * updateRow() or insertRow() methods are called to update the database.
02490    * 
02491    * @param columnName the name of the column
02492    * @param x the new column value
02493    * @exception SQLException if a database-access error occurs
02494    */
02495   public void updateDouble(String columnName, double x) throws SQLException
02496   {
02497     this.updateDouble(findColumn(columnName), x);
02498   }
02499 
02500   /**
02501    * JDBC 2.0 Update a column with a BigDecimal value. The updateXXX() methods
02502    * are used to update column values in the current row, or the insert row. The
02503    * updateXXX() methods do not update the underlying database, instead the
02504    * updateRow() or insertRow() methods are called to update the database.
02505    * 
02506    * @param columnName the name of the column
02507    * @param x the new column value
02508    * @exception SQLException if a database-access error occurs
02509    */
02510   public void updateBigDecimal(String columnName, BigDecimal x)
02511       throws SQLException
02512   {
02513     this.updateBigDecimal(findColumn(columnName), x);
02514   }
02515 
02516   /**
02517    * JDBC 2.0 Update a column with a String value. The updateXXX() methods are
02518    * used to update column values in the current row, or the insert row. The
02519    * updateXXX() methods do not update the underlying database, instead the
02520    * updateRow() or insertRow() methods are called to update the database.
02521    * 
02522    * @param columnName the name of the column
02523    * @param x the new column value
02524    * @exception SQLException if a database-access error occurs
02525    */
02526   public void updateString(String columnName, String x) throws SQLException
02527   {
02528     this.updateString(findColumn(columnName), x);
02529   }
02530 
02531   /**
02532    * JDBC 2.0 Update a column with a byte array value. The updateXXX() methods
02533    * are used to update column values in the current row, or the insert row. The
02534    * updateXXX() methods do not update the underlying database, instead the
02535    * updateRow() or insertRow() methods are called to update the database.
02536    * 
02537    * @param columnName the name of the column
02538    * @param x the new column value
02539    * @exception SQLException if a database-access error occurs
02540    */
02541   public void updateBytes(String columnName, byte x[]) throws SQLException
02542   {
02543     this.updateBytes(findColumn(columnName), x);
02544   }
02545 
02546   /**
02547    * JDBC 2.0 Update a column with a Date value. The updateXXX() methods are
02548    * used to update column values in the current row, or the insert row. The
02549    * updateXXX() methods do not update the underlying database, instead the
02550    * updateRow() or insertRow() methods are called to update the database.
02551    * 
02552    * @param columnName the name of the column
02553    * @param x the new column value
02554    * @exception SQLException if a database-access error occurs
02555    */
02556   public void updateDate(String columnName, java.sql.Date x)
02557       throws SQLException
02558   {
02559     this.updateDate(findColumn(columnName), x);
02560   }
02561 
02562   /**
02563    * JDBC 2.0 Update a column with a Time value. The updateXXX() methods are
02564    * used to update column values in the current row, or the insert row. The
02565    * updateXXX() methods do not update the underlying database, instead the
02566    * updateRow() or insertRow() methods are called to update the database.
02567    * 
02568    * @param columnName the name of the column
02569    * @param x the new column value
02570    * @exception SQLException if a database-access error occurs
02571    */
02572   public void updateTime(String columnName, java.sql.Time x)
02573       throws SQLException
02574   {
02575     this.updateTime(findColumn(columnName), x);
02576   }
02577 
02578   /**
02579    * JDBC 2.0 Update a column with a Timestamp value. The updateXXX() methods
02580    * are used to update column values in the current row, or the insert row. The
02581    * updateXXX() methods do not update the underlying database, instead the
02582    * updateRow() or insertRow() methods are called to update the database.
02583    * 
02584    * @param columnName the name of the column
02585    * @param x the new column value
02586    * @exception SQLException if a database-access error occurs
02587    */
02588   public void updateTimestamp(String columnName, java.sql.Timestamp x)
02589       throws SQLException
02590   {
02591     this.updateTimestamp(findColumn(columnName), x);
02592   }
02593 
02594   /**
02595    * JDBC 2.0 Update a column with an ascii stream value. The updateXXX()
02596    * methods are used to update column values in the current row, or the insert
02597    * row. The updateXXX() methods do not update the underlying database, instead
02598    * the updateRow() or insertRow() methods are called to update the database.
02599    * 
02600    * @param columnName the name of the column
02601    * @param x the new column value
02602    * @param length of the stream
02603    * @exception SQLException if a database-access error occurs
02604    */
02605   public void updateAsciiStream(String columnName, java.io.InputStream x,
02606       int length) throws SQLException
02607   {
02608     this.updateAsciiStream(findColumn(columnName), x, length);
02609   }
02610 
02611   /**
02612    * JDBC 2.0 Update a column with a binary stream value. The updateXXX()
02613    * methods are used to update column values in the current row, or the insert
02614    * row. The updateXXX() methods do not update the underlying database, instead
02615    * the updateRow() or insertRow() methods are called to update the database.
02616    * 
02617    * @param columnName the name of the column
02618    * @param x the new column value
02619    * @param length of the stream
02620    * @exception SQLException if a database-access error occurs
02621    */
02622   public void updateBinaryStream(String columnName, java.io.InputStream x,
02623       int length) throws SQLException
02624   {
02625     this.updateBinaryStream(findColumn(columnName), x, length);
02626   }
02627 
02628   /**
02629    * JDBC 2.0 Update a column with a character stream value. The updateXXX()
02630    * methods are used to update column values in the current row, or the insert
02631    * row. The updateXXX() methods do not update the underlying database, instead
02632    * the updateRow() or insertRow() methods are called to update the database.
02633    * 
02634    * @param columnName the name of the column
02635    * @param reader the stream
02636    * @param length of the stream
02637    * @exception SQLException if a database-access error occurs
02638    */
02639   public void updateCharacterStream(String columnName, java.io.Reader reader,
02640       int length) throws SQLException
02641   {
02642     this.updateCharacterStream(findColumn(columnName), reader, length);
02643   }
02644 
02645   /**
02646    * JDBC 2.0 Update a column with an Object value. The updateXXX() methods are
02647    * used to update column values in the current row, or the insert row. The
02648    * updateXXX() methods do not update the underlying database, instead the
02649    * updateRow() or insertRow() methods are called to update the database.
02650    * 
02651    * @param columnName the name of the column
02652    * @param x the new column value
02653    * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
02654    *          this is the number of digits after the decimal. For all other
02655    *          types this value will be ignored.
02656    * @exception SQLException if a database-access error occurs
02657    */
02658   public void updateObject(String columnName, Object x, int scale)
02659       throws SQLException
02660   {
02661     this.updateObject(findColumn(columnName), x, scale);
02662   }
02663 
02664   /**
02665    * JDBC 2.0 Update a column with an Object value. The updateXXX() methods are
02666    * used to update column values in the current row, or the insert row. The
02667    * updateXXX() methods do not update the underlying database, instead the
02668    * updateRow() or insertRow() methods are called to update the database.
02669    * 
02670    * @param columnName the name of the column
02671    * @param x the new column value
02672    * @exception SQLException if a database-access error occurs
02673    */
02674   public void updateObject(String columnName, Object x) throws SQLException
02675   {
02676     this.updateObject(findColumn(columnName), x);
02677   }
02678 
02679   /**
02680    * JDBC 2.0 Insert the contents of the insert row into the result set and the
02681    * database. Must be on the insert row when this method is called.
02682    * 
02683    * @exception SQLException if a database-access error occurs, if called when
02684    *              not on the insert row, or if all non-nullable columns in the
02685    *              insert row have not been given a value
02686    */
02687   public void insertRow() throws SQLException
02688   {
02689     checkIfClosed();
02690 
02691     if (!inserting)
02692       throw new SQLException("insertRow cannot be called "
02693           + "when the cursor is not on the insert row");
02694 
02695     // Insert row in underlying database
02696     try
02697     {
02698       insertStatement.executeUpdate();
02699     }
02700     finally
02701     {
02702       // Clean up
02703       insertStatement.clearParameters();
02704     }
02705 
02706     // Insert row in this ResultSet
02707     if (data == null)
02708       data = new ArrayList();
02709     data.add(tempRow);
02710     nbOfRows++;
02711 
02712     // Prepare for a new insert
02713     tempRow = new Object[nbOfColumns];
02714   }
02715 
02716   /**
02717    * JDBC 2.0 Update the underlying database with the new contents of the
02718    * current row. Cannot be called when on the insert row.
02719    * 
02720    * @exception SQLException if a database-access error occurs, or if called
02721    *              when on the insert row
02722    */
02723   public void updateRow() throws SQLException
02724   {
02725     checkIfClosed();
02726 
02727     if (inserting)
02728       throw new SQLException("updateRow cannot be called "
02729           + "when the cursor is on the insert row");
02730 
02731     if (!updating)
02732       return;
02733 
02734     // Add primary key info from current row
02735     for (int i = 0; i < primaryKeyColumns.length; ++i)
02736       updateStatement.setObject(nbOfColumns + i + 1, ((Object[]) data
02737           .get(currentRow))[findColumn(primaryKeyColumns[i]) - 1]);
02738 
02739     // Update row in underlying database
02740     try
02741     {
02742       updateStatement.executeUpdate();
02743     }
02744     finally
02745     {
02746       // Clean up
02747       updateStatement.clearParameters();
02748     }
02749 
02750     // Update row in this ResultSet
02751     data.set(currentRow, tempRow);
02752 
02753     // Clean up
02754     tempRow = null;
02755     updating = false;
02756   }
02757 
02758   /**
02759    * JDBC 2.0 Delete the current row from the result set and the underlying
02760    * database. Cannot be called when on the insert row.
02761    * 
02762    * @exception SQLException if a database-access error occurs, or if called
02763    *              when on the insert row.
02764    */
02765   public void deleteRow() throws SQLException
02766   {
02767     checkIfClosed();
02768 
02769     if (inserting)
02770       throw new SQLException("deleteRow cannot be called "
02771           + "when the cursor is on the insert row");
02772 
02773     this.checkRowPos();
02774 
02775     if (deleteStatement == null)
02776       this.buildDeleteStatement();
02777 
02778     // Add primary key info from current row
02779     for (int i = 0; i < primaryKeyColumns.length; ++i)
02780       deleteStatement
02781           .setObject(
02782               i + 1,
02783               ((Object[]) data.get(currentRow))[findColumn(primaryKeyColumns[i]) - 1]);
02784 
02785     // Delete row from underlying database
02786     try
02787     {
02788       deleteStatement.executeUpdate();
02789     }
02790     finally
02791     {
02792       // Clean up
02793       deleteStatement.clearParameters();
02794     }
02795 
02796     // Delete row from this ResultSet
02797     data.remove(currentRow);
02798     nbOfRows--;
02799 
02800     // Deleting cancels all updates on the row
02801     if (updating)
02802       this.cancelRowUpdates();
02803   }
02804 
02805   /**
02806    * JDBC 2.0 Refresh the value of the current row with its current value in the
02807    * database. Cannot be called when on the insert row. The refreshRow() method
02808    * provides a way for an application to explicitly tell the JDBC driver to
02809    * refetch a row(s) from the database. An application may want to call
02810    * refreshRow() when caching or prefetching is being done by the JDBC driver
02811    * to fetch the latest value of a row from the database. The JDBC driver may
02812    * actually refresh multiple rows at once if the fetch size is greater than
02813    * one. All values are refetched subject to the transaction isolation level
02814    * and cursor sensitivity. If refreshRow() is called after calling
02815    * updateXXX(), but before calling updateRow() then the updates made to the
02816    * row are lost. Calling refreshRow() frequently will likely slow performance.
02817    * 
02818    * @exception SQLException if a database-access error occurs, or if called
02819    *              when on the insert row.
02820    */
02821   public void refreshRow() throws SQLException
02822   {
02823     checkIfClosed();
02824 
02825     if (inserting)
02826       throw new SQLException("refreshRow cannot be called "
02827           + "when the cursor is on the insert row");
02828 
02829     this.checkRowPos();
02830 
02831     if (refreshStatement == null)
02832       this.buildRefreshStatement();
02833 
02834     // Add primary key info from current row
02835     for (int i = 0; i < primaryKeyColumns.length; ++i)
02836       refreshStatement
02837           .setObject(
02838               i + 1,
02839               ((Object[]) data.get(currentRow))[findColumn(primaryKeyColumns[i]) - 1]);
02840 
02841     // Retrieve row from underlying database
02842     DriverResultSet res;
02843     try
02844     {
02845       res = (DriverResultSet) refreshStatement.executeQuery();
02846     }
02847     finally
02848     {
02849       // Clean up
02850       refreshStatement.clearParameters();
02851     }
02852 
02853     // Refresh row in this ResultSet
02854     try
02855     {
02856       data.set(currentRow, res.data.get(0));
02857     }
02858     catch (NullPointerException e)
02859     {
02860       throw new SQLException("The current row has been "
02861           + "removed from the database");
02862     }
02863     finally
02864     {
02865       // Clean up
02866       res.close();
02867     }
02868 
02869     // Refreshing cancels all updates on the row
02870     if (updating)
02871       this.cancelRowUpdates();
02872   }
02873 
02874   /**
02875    * JDBC 2.0 The cancelRowUpdates() method may be called after calling an
02876    * updateXXX() method(s) and before calling updateRow() to rollback the
02877    * updates made to a row. If no updates have been made or updateRow() has
02878    * already been called, then this method has no effect.
02879    * 
02880    * @exception SQLException if a database-access error occurs, or if called
02881    *              when on the insert row.
02882    */
02883   public void cancelRowUpdates() throws SQLException
02884   {
02885     checkIfClosed();
02886 
02887     if (inserting)
02888       throw new SQLException("cancelRowUpdates cannot be "
02889           + "called when the cursor is on the insert row");
02890 
02891     if (!updating)
02892       return;
02893 
02894     updateStatement.clearParameters();
02895     tempRow = null;
02896     updating = false;
02897   }
02898 
02899   /**
02900    * JDBC 2.0 Move to the insert row. The current cursor position is remembered
02901    * while the cursor is positioned on the insert row. The insert row is a
02902    * special row associated with an updatable result set. It is essentially a
02903    * buffer where a new row may be constructed by calling the updateXXX()
02904    * methods prior to inserting the row into the result set. Only the
02905    * updateXXX(), getXXX(), and insertRow() methods may be called when the
02906    * cursor is on the insert row. All of the columns in a result set must be
02907    * given a value each time this method is called before calling insertRow().
02908    * UpdateXXX()must be called before getXXX() on a column.
02909    * 
02910    * @exception SQLException if a database-access error occurs, or the result
02911    *              set is not updatable
02912    */
02913   public void moveToInsertRow() throws SQLException
02914   {
02915     checkIfClosed();
02916 
02917     if (inserting)
02918       return;
02919 
02920     if (insertStatement == null)
02921       this.buildInsertStatement();
02922 
02923     tempRow = new Object[nbOfColumns];
02924     inserting = true;
02925   }
02926 
02927   /**
02928    * JDBC 2.0 Move the cursor to the remembered cursor position, usually the
02929    * current row. Has no effect unless the cursor is on the insert row.
02930    * 
02931    * @exception SQLException if a database-access error occurs, or the result
02932    *              set is not updatable
02933    */
02934   public void moveToCurrentRow() throws SQLException
02935   {
02936     checkIfClosed();
02937 
02938     if (!inserting)
02939       return;
02940 
02941     insertStatement.clearParameters();
02942     tempRow = null;
02943     inserting = false;
02944   }
02945 
02946   //
02947   // ------------------------------------------
02948   // ResultSet meta-data related functions
02949   // ------------------------------------------
02950   //
02951 
02952   /**
02953    * JDBC 2.0 Return the type of this result set. The type is determined based
02954    * on the statement that created the result set.
02955    * 
02956    * @return TYPE_FORWARD_ONLY, TYPE_SCROLL_INSENSITIVE, or
02957    *         TYPE_SCROLL_SENSITIVE
02958    * @exception SQLException if a database-access error occurs
02959    */
02960   public int getType() throws SQLException
02961   {
02962     return resultSetType;
02963   }
02964 
02965   /**
02966    * JDBC 2.0 Return the concurrency of this result set. The concurrency used is
02967    * determined by the statement that created the result set.
02968    * 
02969    * @return CONCUR_READ_ONLY or CONCUR_UPDATABLE
02970    * @exception SQLException if a database-access error occurs
02971    */
02972 
02973   public int getConcurrency() throws SQLException
02974   {
02975     return resultSetConcurrency;
02976   }
02977 
02978   /**
02979    * Closes the remote ResultSet if the ResultSet was streamed else just closes
02980    * the ResultSet locally.
02981    * 
02982    * @exception SQLException if a database access error occurs
02983    */
02984   public void close() throws SQLException
02985   {
02986     if (hasMoreData)
02987       owningStatement.connection.closeRemoteResultSet(cursorName);
02988     isClosed = true;
02989   }
02990 
02991   /**
02992    * A column may have the value of SQL NULL; wasNull() reports whether the last
02993    * column read had this special value. Note that you must first call getXXX on
02994    * a column to try to read its value and then call wasNull() to find if the
02995    * value was SQL NULL
02996    * 
02997    * @return <code>true</code> if the last column read was SQL NULL
02998    * @exception SQLException if a database access error occurred
02999    */
03000 
03001   public boolean wasNull() throws SQLException
03002   {
03003     return wasNullFlag;
03004   }
03005 
03006   /**
03007    * JDBC 2.0 Return the <code>Statement</code> that produced the
03008    * <code>ResultSet</code>.
03009    * 
03010    * @return the <code>Statement</code> that produced the
03011    *         <code>ResultSet</code>, or null if the result was produced some
03012    *         other way.
03013    * @exception SQLException if a database-access error occurs
03014    */
03015   public java.sql.Statement getStatement() throws SQLException
03016   {
03017     return owningStatement;
03018   }
03019 
03020   /**
03021    * Set the ResultSet data with the given ArrayList. This function is used by
03022    * the ResultSet streaming feature.
03023    * <p>
03024    * Note that metadata (currentRow, nbOfRows, ...) are not updated.
03025    * 
03026    * @param newData new ResultSet data
03027    */
03028   protected void setData(ArrayList newData)
03029   {
03030     data = newData;
03031   }
03032 
03033   /**
03034    * Set the hasMoreData boolean (is there more data to fetch from the
03035    * controller). This function is used by the ResultSet streaming feature.
03036    * 
03037    * @param hasMore new value for hasMoreData
03038    */
03039   protected void setHasMoreData(boolean hasMore)
03040   {
03041     hasMoreData = hasMore;
03042   }
03043 
03044   /**
03045    * The numbers, types and properties of a <code>ResultSet</code>'s columns
03046    * are provided by the <code>getMetaData</code> method
03047    * 
03048    * @return a description of the <code>ResultSet</code>'s columns
03049    * @exception SQLException if a database access error occurs
03050    */
03051   public java.sql.ResultSetMetaData getMetaData() throws SQLException
03052   {
03053     return new ResultSetMetaData(this);
03054   }
03055 
03056   /**
03057    * Map a <code>ResultSet</code> column name to a <code>ResultSet</code>
03058    * column index
03059    * 
03060    * @param columnName the name of the column
03061    * @return the column index
03062    * @exception SQLException if a database access error occurs
03063    */
03064   public int findColumn(String columnName) throws SQLException
03065   {
03066     if (columnNameToIndex == null)
03067       buildIndexMapping();
03068 
03069     Integer index = (Integer) columnNameToIndex.get(columnName);
03070 
03071     if (index == null)
03072       index = (Integer) fullColumnNameToIndex.get(columnName);
03073 
03074     if (index != null)
03075       return index.intValue() + 1;
03076     else
03077     {
03078       // Try this inefficient way, now
03079       String columnNameUC = columnName.toUpperCase();
03080       for (int i = 0; i < nbOfColumns; i++)
03081       {
03082         if (fields[i].getFieldName().toUpperCase().equals(columnNameUC))
03083           return i + 1;
03084         else if (fields[i].getFullName().toUpperCase().equals(columnNameUC))
03085           return i + 1;
03086       }
03087       throw new java.sql.SQLException("Column '" + columnName + "' not found.");
03088     }
03089   }
03090 
03091   // ****************************************************************
03092   //
03093   //                       END OF PUBLIC INTERFACE
03094   //
03095   // ****************************************************************
03096 
03097   /**
03098    * Creates a new <code>DriverResultSet</code>.
03099    * 
03100    * @param fields an array of <code>Field</code> objects (basically, the
03101    *          <code>ResultSet</code> meta data)
03102    * @param resultData array of the actual data (data[row][column])
03103    */
03104   public DriverResultSet(Field[] fields, ArrayList resultData)
03105   {
03106     currentRow = -1;
03107     this.fields = fields;
03108     data = resultData;
03109     if (data == null)
03110       nbOfRows = 0;
03111     else
03112       nbOfRows = data.size();
03113     nbOfColumns = fields.length;
03114     isClosed = false;
03115   }
03116 
03117   /**
03118    * Creates a new <code>DriverResultSet</code> object from information we get
03119    * back from a ControllerResultSet.
03120    * 
03121    * @param fields an array of <code>Field</code> objects (basically, the
03122    *          <code>ResultSet</code> meta data)
03123    * @param resultData array of the actual data (data[row][column])
03124    * @param crsHasMoreData true if remote ControllerResultSet has more data to
03125    *          fetch
03126    * @param cursorName cursor name for a streamable ResultSet
03127    */
03128   public DriverResultSet(Field[] fields, ArrayList resultData,
03129       boolean crsHasMoreData, String cursorName)
03130   {
03131     this(fields, resultData);
03132     this.cursorName = cursorName;
03133     hasMoreData = crsHasMoreData;
03134   }
03135 
03136   /**
03137    * Set the statement.
03138    * 
03139    * @param stmt The statement to set
03140    * @throws SQLException if an error occurs
03141    */
03142   protected void setStatement(Statement stmt) throws SQLException
03143   {
03144     owningStatement = stmt;
03145     fetchSize = stmt.getFetchSize();
03146     resultSetConcurrency = stmt.getResultSetConcurrency();
03147     resultSetType = stmt.getResultSetType();
03148   }
03149 
03150   /**
03151    * Builds a hash between column names and their indices for fast retrieval.
03152    */
03153   private void buildIndexMapping()
03154   {
03155     int numFields = nbOfColumns;
03156 
03157     columnNameToIndex = new Hashtable();
03158     fullColumnNameToIndex = new Hashtable();
03159 
03160     for (int i = 0; i < numFields; i++)
03161     {
03162       Integer index = new Integer(i);
03163 
03164       String columnName = fields[i].getFieldName();
03165       String fullColumnName = fields[i].getFullName();
03166       if (columnName != null)
03167       {
03168         columnNameToIndex.put(fields[i].getFieldName(), index);
03169         columnNameToIndex.put(fields[i].getFieldName().toUpperCase(), index);
03170         columnNameToIndex.put(fields[i].getFieldName().toLowerCase(), index);
03171       }
03172 
03173       if (fullColumnName != null)
03174       {
03175         fullColumnNameToIndex.put(fields[i].getFullName(), index);
03176         fullColumnNameToIndex.put(fields[i].getFullName().toUpperCase(), index);
03177         fullColumnNameToIndex.put(fields[i].getFullName().toLowerCase(), index);
03178       }
03179     }
03180   }
03181 
03182   /**
03183    * Builds a delete statement for deleting rows with Updatable ResultSets
03184    * 
03185    * @throws SQLException
03186    */
03187   private void buildDeleteStatement() throws SQLException
03188   {
03189     // Check that ResultSet can be updated
03190     this.checkUpdatability();
03191 
03192     // Build delete statement for this ResultSet
03193     StringBuffer sb = new StringBuffer();
03194     sb.append("DELETE FROM ");
03195     sb.append(fields[0].getTableName());
03196     sb.append(" WHERE ");
03197     for (int i = 0; i < primaryKeyColumns.length; ++i)
03198     {
03199       if (i > 0)
03200         sb.append(" AND ");
03201       sb.append(primaryKeyColumns[i]);
03202       sb.append(" = ?");
03203     }
03204 
03205     // set delete statement
03206     deleteStatement = this.owningStatement.getConnection().prepareStatement(
03207         sb.toString());
03208   }
03209 
03210   /**
03211    * Builds a insert statement for inserting rows with Updatable ResultSets
03212    * 
03213    * @throws SQLException
03214    */
03215   private void buildInsertStatement() throws SQLException
03216   {
03217     // Check that ResultSet can be updated
03218     this.checkUpdatability();
03219 
03220     // Build insert statement for this ResultSet
03221     StringBuffer sb = new StringBuffer();
03222     sb.append("INSERT INTO ");
03223     sb.append(fields[0].getTableName());
03224     sb.append(" (");
03225     for (int i = 0; i < fields.length; ++i)
03226     {
03227       if (i > 0)
03228         sb.append(", ");
03229       sb.append(fields[i].getFieldName());
03230     }
03231     sb.append(") VALUES (");
03232     for (int i = 0; i < fields.length; ++i)
03233     {
03234       if (i > 0)
03235         sb.append(", ");
03236       sb.append("?");
03237     }
03238     sb.append(")");
03239 
03240     // set insert statement
03241     insertStatement = this.owningStatement.getConnection().prepareStatement(
03242         sb.toString());
03243   }
03244 
03245   /**
03246    * Builds a select statement for refreshing rows in Updatable ResultSets
03247    * 
03248    * @throws SQLException
03249    */
03250   private void buildRefreshStatement() throws SQLException
03251   {
03252     // Check that ResultSet can be updated
03253     this.checkUpdatability();
03254 
03255     // Build refresh statement for this ResultSet
03256     StringBuffer sb = new StringBuffer();
03257     sb.append("SELECT ");
03258     for (int i = 0; i < fields.length; ++i)
03259     {
03260       if (i > 0)
03261         sb.append(", ");
03262       sb.append(fields[i].getFieldName());
03263     }
03264     sb.append(" FROM ");
03265     sb.append(fields[0].getTableName());
03266     sb.append(" WHERE ");
03267     for (int i = 0; i < primaryKeyColumns.length; ++i)
03268     {
03269       if (i > 0)
03270         sb.append(" AND ");
03271       sb.append(primaryKeyColumns[i]);
03272       sb.append(" = ?");
03273     }
03274 
03275     // set refresh statement
03276     refreshStatement = this.owningStatement.getConnection().prepareStatement(
03277         sb.toString());
03278   }
03279 
03280   /**
03281    * Builds an update statement for updating rows with Updatable ResultSets
03282    * 
03283    * @throws SQLException
03284    */
03285   private void buildUpdateStatement() throws SQLException
03286   {
03287     // Check that ResultSet can be updated
03288     this.checkUpdatability();
03289 
03290     // Build update statement for this ResultSet
03291     StringBuffer sb = new StringBuffer();
03292     sb.append("UPDATE ");
03293     sb.append(fields[0].getTableName());
03294     sb.append(" SET ");
03295     for (int i = 0; i < fields.length; ++i)
03296     {
03297       if (i > 0)
03298         sb.append(", ");
03299       sb.append(fields[i].getFieldName());
03300       sb.append(" = ?");
03301     }
03302     sb.append(" WHERE ");
03303     for (int i = 0; i < primaryKeyColumns.length; ++i)
03304     {
03305       if (i > 0)
03306         sb.append(" AND ");
03307       sb.append(primaryKeyColumns[i]);
03308       sb.append(" = ?");
03309     }
03310 
03311     // set update statement
03312     updateStatement = this.owningStatement.getConnection().prepareStatement(
03313         sb.toString());
03314   }
03315 
03316   /**
03317    * Retrieves the primary key for the table referenced by this ResultSet
03318    * 
03319    * @throws SQLException
03320    */
03321   private void extractPrimaryKey() throws SQLException
03322   {
03323     ResultSet res = ((Connection) this.owningStatement.getConnection())
03324         .getPrimaryKeys(null, null, fields[0].getTableName());
03325 
03326     try
03327     {
03328       primaryKeyColumns = new String[((DriverResultSet) res).nbOfRows];
03329       while (res.next())
03330         primaryKeyColumns[res.getRow() - 1] = res.getString(4);
03331     }
03332     finally
03333     {
03334       // Clean up
03335       res.close();
03336     }
03337   }
03338 
03339   /**
03340    * Basic checks for Updatable ResultSets
03341    * 
03342    * @throws SQLException
03343    */
03344   private void checkUpdatability() throws SQLException
03345   {
03346     // Check ResultSet Concurrency type
03347     switch (resultSetConcurrency)
03348     {
03349       case ResultSet.CONCUR_READ_ONLY :
03350         throw new SQLException("Cannot update ResultSet with "
03351             + "concurrency mode CONCUR_READ_ONLY");
03352       case ResultSet.CONCUR_UPDATABLE :
03353         break;
03354       default :
03355         throw new SQLException("Invalid ResultSet concurrency mode: "
03356             + resultSetConcurrency);
03357     }
03358 
03359     // Check that the query selects only one table
03360     String tableName = fields[0].getTableName();
03361     for (int i = 1; i < nbOfColumns; ++i)
03362       if (!tableName.equals(fields[i].getTableName()))
03363         throw new SQLException(UPDATEABLE_MESSAGE);
03364 
03365     // Check if need to get primary keys
03366     if (primaryKeyColumns == null)
03367       this.extractPrimaryKey();
03368 
03369     // Check that the query selects the full primary key
03370     for (int i = 0; i < primaryKeyColumns.length; ++i)
03371       try
03372       {
03373         findColumn(primaryKeyColumns[i]);
03374       }
03375       catch (SQLException e)
03376       {
03377         throw new SQLException(UPDATEABLE_MESSAGE);
03378       }
03379   }
03380 
03381   /**
03382    * Sanity checks for result parsing
03383    * 
03384    * @param columnIndex the column to check
03385    * @throws SQLException if an error occurs
03386    */
03387   private void checkRowAndColPosAndSetNullFlag(int columnIndex)
03388       throws SQLException
03389   {
03390     checkIfClosed();
03391 
03392     if (!inserting)
03393       checkRowPos();
03394 
03395     if (fields == null)
03396       throw new java.sql.SQLException("Query generated no fields for ResultSet");
03397 
03398     if (columnIndex < 1 || columnIndex > nbOfColumns)
03399       throw new java.sql.SQLException("Column Index out of range ( "
03400           + columnIndex + " > " + nbOfColumns + ").");
03401 
03402     try
03403     {
03404       Object obj;
03405       if (inserting || updating)
03406         obj = tempRow[columnIndex - 1];
03407       else
03408         obj = ((Object[]) data.get(currentRow))[columnIndex - 1];
03409 
03410       if (obj == null)
03411         wasNullFlag = true;
03412       else
03413         wasNullFlag = false;
03414     }
03415     catch (NullPointerException e)
03416     {
03417       wasNullFlag = true;
03418     }
03419   }
03420 
03421   /**
03422    * Checks that the cursor is on row in the ResultSet
03423    * 
03424    * @throws SQLException
03425    */
03426   private void checkRowPos() throws SQLException
03427   {
03428     if (currentRow < 0)
03429       throw new SQLException("Before start of result set");
03430 
03431     if (currentRow == nbOfRows)
03432       throw new SQLException("After end of result set");
03433   }
03434 
03435   /**
03436    * Checks that the update flag is set when updating a row. The first time an
03437    * update is done on a row this method will prepare the ResultSet for update
03438    * 
03439    * @throws SQLException
03440    */
03441   private void checkUpdateFlagAndPrepareUpdateIfNeeded() throws SQLException
03442   {
03443     if (updating)
03444       return;
03445 
03446     this.checkRowPos();
03447 
03448     if (updateStatement == null)
03449       this.buildUpdateStatement();
03450 
03451     tempRow = (Object[]) ((Object[]) data.get(currentRow)).clone();
03452 
03453     for (int i = 0; i < nbOfColumns; ++i)
03454       updateStatement.setObject(i + 1, tempRow[i]);
03455 
03456     updating = true;
03457   }
03458 
03459   /**
03460    * Check if the ResultSet if closed and throws a SQLException if so.
03461    * 
03462    * @throws SQLException if the ResultSet is closed
03463    */
03464   private void checkIfClosed() throws SQLException
03465   {
03466     if (isClosed)
03467       throw new SQLException("Trying to access a closed ResultSet");
03468   }
03469 
03470   //-------------------------- JDBC 3.0
03471   // ----------------------------------------
03472 
03473   /**
03474    * Retrieves the value of the designated column in the current row of this
03475    * <code>ResultSet</code> object as a <code>java.net.URL</code> object in
03476    * the Java programming language.
03477    * 
03478    * @param columnIndex the index of the column 1 is the first, 2 is the
03479    *          second,...
03480    * @return the column value as a <code>java.net.URL</code> object; if the
03481    *         value is SQL <code>NULL</code>, the value returned is
03482    *         <code>null</code> in the Java programming language
03483    * @exception SQLException if a database access error occurs, or if a URL is
03484    *              malformed
03485    * @since JDK 1.4
03486    */
03487   public java.net.URL getURL(int columnIndex) throws SQLException
03488   {
03489     throw new NotImplementedException("getURL");
03490   }
03491 
03492   /**
03493    * Retrieves the value of the designated column in the current row of this
03494    * <code>ResultSet</code> object as a <code>java.net.URL</code> object in
03495    * the Java programming language.
03496    * 
03497    * @param columnName the SQL name of the column
03498    * @return the column value as a <code>java.net.URL</code> object; if the
03499    *         value is SQL <code>NULL</code>, the value returned is
03500    *         <code>null</code> in the Java programming language
03501    * @exception SQLException if a database access error occurs or if a URL is
03502    *              malformed
03503    * @since JDK 1.4
03504    */
03505   public java.net.URL getURL(String columnName) throws SQLException
03506   {
03507     throw new NotImplementedException("getURL");
03508   }
03509 
03510   /**
03511    * Updates the designated column with a <code>java.sql.Ref</code> value. The
03512    * updater methods are used to update column values in the current row or the
03513    * insert row. The updater methods do not update the underlying database;
03514    * instead the <code>updateRow</code> or <code>insertRow</code> methods
03515    * are called to update the database.
03516    * 
03517    * @param columnIndex the first column is 1, the second is 2, ...
03518    * @param x the new column value
03519    * @exception SQLException if a database access error occurs
03520    * @since JDK 1.4
03521    */
03522   public void updateRef(int columnIndex, java.sql.Ref x) throws SQLException
03523   {
03524     throw new NotImplementedException("updateRef");
03525   }
03526 
03527   /**
03528    * Updates the designated column with a <code>java.sql.Ref</code> value. The
03529    * updater methods are used to update column values in the current row or the
03530    * insert row. The updater methods do not update the underlying database;
03531    * instead the <code>updateRow</code> or <code>insertRow</code> methods
03532    * are called to update the database.
03533    * 
03534    * @param columnName the name of the column
03535    * @param x the new column value
03536    * @exception SQLException if a database access error occurs
03537    * @since JDK 1.4
03538    */
03539   public void updateRef(String columnName, java.sql.Ref x) throws SQLException
03540   {
03541     throw new NotImplementedException("updateRef");
03542   }
03543 
03544   /**
03545    * Updates the designated column with a <code>java.sql.Blob</code> value.
03546    * The updater methods are used to update column values in the current row or
03547    * the insert row. The updater methods do not update the underlying database;
03548    * instead the <code>updateRow</code> or <code>insertRow</code> methods
03549    * are called to update the database.
03550    * 
03551    * @param columnIndex the first column is 1, the second is 2, ...
03552    * @param x the new column value
03553    * @exception SQLException if a database access error occurs
03554    * @since JDK 1.4
03555    */
03556   public void updateBlob(int columnIndex, java.sql.Blob x) throws SQLException
03557   {
03558     throw new NotImplementedException("updateBlob");
03559   }
03560 
03561   /**
03562    * Updates the designated column with a <code>java.sql.Blob</code> value.
03563    * The updater methods are used to update column values in the current row or
03564    * the insert row. The updater methods do not update the underlying database;
03565    * instead the <code>updateRow</code> or <code>insertRow</code> methods
03566    * are called to update the database.
03567    * 
03568    * @param columnName the name of the column
03569    * @param x the new column value
03570    * @exception SQLException if a database access error occurs
03571    * @since JDK 1.4
03572    */
03573   public void updateBlob(String columnName, java.sql.Blob x)
03574       throws SQLException
03575   {
03576     throw new NotImplementedException("updateBlob");
03577   }
03578 
03579   /**
03580    * Updates the designated column with a <code>java.sql.Clob</code> value.
03581    * The updater methods are used to update column values in the current row or
03582    * the insert row. The updater methods do not update the underlying database;
03583    * instead the <code>updateRow</code> or <code>insertRow</code> methods
03584    * are called to update the database.
03585    * 
03586    * @param columnIndex the first column is 1, the second is 2, ...
03587    * @param x the new column value
03588    * @exception SQLException if a database access error occurs
03589    * @since JDK 1.4
03590    */
03591   public void updateClob(int columnIndex, java.sql.Clob x) throws SQLException
03592   {
03593     throw new NotImplementedException("updateClob");
03594   }
03595 
03596   /**
03597    * Updates the designated column with a <code>java.sql.Clob</code> value.
03598    * The updater methods are used to update column values in the current row or
03599    * the insert row. The updater methods do not update the underlying database;
03600    * instead the <code>updateRow</code> or <code>insertRow</code> methods
03601    * are called to update the database.
03602    * 
03603    * @param columnName the name of the column
03604    * @param x the new column value
03605    * @exception SQLException if a database access error occurs
03606    * @since JDK 1.4
03607    */
03608   public void updateClob(String columnName, java.sql.Clob x)
03609       throws SQLException
03610   {
03611     throw new NotImplementedException("updateClob");
03612   }
03613 
03614   /**
03615    * Updates the designated column with a <code>java.sql.Array</code> value.
03616    * The updater methods are used to update column values in the current row or
03617    * the insert row. The updater methods do not update the underlying database;
03618    * instead the <code>updateRow</code> or <code>insertRow</code> methods
03619    * are called to update the database.
03620    * 
03621    * @param columnIndex the first column is 1, the second is 2, ...
03622    * @param x the new column value
03623    * @exception SQLException if a database access error occurs
03624    * @since JDK 1.4
03625    */
03626   public void updateArray(int columnIndex, java.sql.Array x)
03627       throws SQLException
03628   {
03629     throw new NotImplementedException("updateArray");
03630   }
03631 
03632   /**
03633    * Updates the designated column with a <code>java.sql.Array</code> value.
03634    * The updater methods are used to update column values in the current row or
03635    * the insert row. The updater methods do not update the underlying database;
03636    * instead the <code>updateRow</code> or <code>insertRow</code> methods
03637    * are called to update the database.
03638    * 
03639    * @param columnName the name of the column
03640    * @param x the new column value
03641    * @exception SQLException if a database access error occurs
03642    * @since JDK 1.4
03643    */
03644   public void updateArray(String columnName, java.sql.Array x)
03645       throws SQLException
03646   {
03647     throw new NotImplementedException("updateArray");
03648   }
03649 
03650   /**
03651    * Get the value of a column in the current row as a Java byte.
03652    * 
03653    * @param columnIndex the first column is 1, the second is 2,...
03654    * @return the column value; 0 if SQL NULL
03655    * @exception SQLException if a database access error occurs
03656    */
03657   public byte getByte(int columnIndex) throws SQLException
03658   {
03659     checkRowAndColPosAndSetNullFlag(columnIndex);
03660 
03661     if (wasNullFlag)
03662       return 0;
03663 
03664     Object obj;
03665     if (inserting || updating)
03666       obj = tempRow[columnIndex - 1];
03667     else
03668       obj = ((Object[]) data.get(currentRow))[columnIndex - 1];
03669 
03670     if (obj instanceof Number)
03671     {
03672       return ((Number) obj).byteValue();
03673     }
03674 
03675     // the object is not of type number we parse the string representation
03676     try
03677     {
03678       String string = obj.toString();
03679       string = string.trim();
03680       return Byte.parseByte(string);
03681     }
03682     catch (NumberFormatException e)
03683     {
03684       throw new SQLException("the value " + obj.toString()
03685           + " is not a valid byte");
03686     }
03687   }
03688 
03689   /**
03690    * @see java.lang.Object#toString()
03691    */
03692   public String toString()
03693   {
03694     return nbOfRows + " rows - " + nbOfColumns + " columns - current row:"
03695         + currentRow + " - hasMoreData:" + hasMoreData + " - isClosed:"
03696         + isClosed;
03697   }
03698 }

Generated on Mon Apr 11 22:01:31 2005 for C-JDBC by  doxygen 1.3.9.1