KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > continuent > sequoia > driver > DriverResultSet


1 /**
2  * Sequoia: Database clustering technology.
3  * Copyright (C) 2002-2004 French National Institute For Research In Computer
4  * Science And Control (INRIA).
5  * Copyright (C) 2005 AmicoSoft, Inc. dba Emic Networks
6  * Contact: sequoia@continuent.org
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  * Initial developer(s): Mark Matthews.
21  * Contributor(s): Emmanuel Cecchet, Andre Austin, Marc Wick, Jean-Bernard
22  * van Zuylen, Marc Herbert, Edward Archibald, Stephane Giron.
23  */

24
25 package org.continuent.sequoia.driver;
26
27 import java.io.ByteArrayInputStream JavaDoc;
28 import java.io.IOException JavaDoc;
29 import java.io.InputStream JavaDoc;
30 import java.io.UnsupportedEncodingException JavaDoc;
31 import java.math.BigDecimal JavaDoc;
32 import java.math.BigInteger JavaDoc;
33 import java.net.URL JavaDoc;
34 import java.nio.CharBuffer JavaDoc;
35 import java.nio.charset.CharacterCodingException JavaDoc;
36 import java.nio.charset.Charset JavaDoc;
37 import java.sql.Clob JavaDoc;
38 import java.sql.PreparedStatement JavaDoc;
39 import java.sql.Ref JavaDoc;
40 import java.sql.ResultSet JavaDoc;
41 import java.sql.SQLException JavaDoc;
42 import java.sql.SQLWarning JavaDoc;
43 import java.sql.Time JavaDoc;
44 import java.sql.Timestamp JavaDoc;
45 import java.util.ArrayList JavaDoc;
46 import java.util.Calendar JavaDoc;
47 import java.util.Hashtable JavaDoc;
48
49 import org.continuent.sequoia.common.exceptions.NotImplementedException;
50 import org.continuent.sequoia.common.exceptions.ProtocolException;
51 import org.continuent.sequoia.common.exceptions.driver.DriverSQLException;
52 import org.continuent.sequoia.common.exceptions.driver.protocol.BackendDriverException;
53 import org.continuent.sequoia.common.protocol.ByteArrayBlob;
54 import org.continuent.sequoia.common.protocol.Field;
55 import org.continuent.sequoia.common.protocol.SQLDataSerialization;
56 import org.continuent.sequoia.common.protocol.StringClob;
57 import org.continuent.sequoia.common.protocol.TypeTag;
58 import org.continuent.sequoia.common.stream.DriverBufferedInputStream;
59
60 /**
61  * A <code>ResultSet</code> provides access to a table of data generated by
62  * executing a Statement. The table rows are retrieved in sequence. Within a row
63  * its column values can be accessed in any order.
64  * <p>
65  * A <code>ResultSet</code> maintains a cursor pointing to its current row of
66  * data. Initially the cursor is positioned before the first row. The 'next'
67  * method moves the cursor to the next row.
68  * <p>
69  * The <code>getXXX</code> methods retrieve column values for the current row.
70  * You can retrieve values either using the index number of the column, or by
71  * using the name of the column. In general using the column index will be more
72  * efficient. Columns are numbered from 1.
73  * <p>
74  * For maximum portability, <code>ResultSet</code> columns within each row
75  * should be read in left-to-right order and each column should be read only
76  * once.
77  * <p>
78  * For the <code>getXXX</code> methods, the JDBC driver attempts to convert
79  * the underlying data to the specified Java type and returns a suitable Java
80  * value. See the JDBC specification for allowable mappings from SQL types to
81  * Java types with the <code>ResultSet</code> <code>getXXX</code> methods.
82  * <p>
83  * Column names used as input to <code>getXXX</code> methods are case
84  * insenstive. When performing a <code>getXXX</code> using a column name, if
85  * several columns have the same name, then the value of the first matching
86  * column will be returned. The column name option is designed to be used when
87  * column names are used in the SQL Query. For columns that are NOT explicitly
88  * named in the query, it is best to use column numbers. If column names were
89  * used there is no way for the programmer to guarentee that they actually refer
90  * to the intended columns.
91  * <P>
92  * A <code>ResultSet</code> is automatically closed by the
93  * <code>Statement</code> that generated it when that <code>Statement</code>
94  * is closed, re-executed, or is used to retrieve the next result from a
95  * sequence of multiple results.
96  * <P>
97  * The number, types and properties of a ResultSet's columns are provided by the
98  * <code>ResultSetMetaData</code> object returned by the
99  * <code>getMetaData</code> method.
100  *
101  * @see java.sql.ResultSetMetaData
102  * @see java.sql.ResultSet
103  * @author Mark Matthews <mmatthew@worldserver.com>
104  * @author <a HREF="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
105  * @author <a HREF="mailto:alexander.laamanen@tecnomen.com">Alexander Laamanen
106  * </a>
107  * @author <a HREF="mailto:Nicolas.Modrzyk@inrialpes.fr">Nicolas Modrzyk </a>
108  * @author <a HREF="mailto:jbvanzuylen@transwide.com">Jean-Bernard van Zuylen
109  * </a>
110  * @author <a HREF="mailto:Marc.Herbert@emicnetworks.com">Marc Herbert </a>
111  * @author <a HREF="mailto:ed.archibald@continuent.com">Edward Archibald</a>
112  * @author <a HREF="mailto:stephane.giron@continuent.com">Stephane Giron</a>
113  * @version 1.0
114  */

115 public class DriverResultSet
116     implements
117       java.sql.ResultSet JavaDoc,
118       java.io.Serializable JavaDoc,
119       java.lang.Cloneable JavaDoc
120 {
121   private static final long serialVersionUID = 7408879935608629886L;
122
123   /** Cursor to current row */
124   protected int currentRow = -1;
125   /** Number of rows */
126   protected int nbOfRows = -1;
127   /** Number of columns */
128   protected int nbOfColumns = -1;
129   /** The results */
130   protected ArrayList JavaDoc data;
131   /** True if there is more data to fetch from the controller */
132   private boolean hasMoreData;
133   /** The fetch direction (not used yet) */
134   protected int fetchDirection = FETCH_FORWARD;
135   /** The fetch size */
136   protected int fetchSize = 0;
137   /** ResultSet cursor name */
138   private String JavaDoc cursorName;
139
140   /** The fields */
141   protected Field[] fields;
142
143   /** Pointers to column-specific de/serializer */
144   private SQLDataSerialization.Serializer[] serializers;
145
146   /** for wasNull() */
147   protected boolean wasNullFlag = false;
148   /** column name -> index in ResultSet data array */
149   protected transient Hashtable JavaDoc lowerNameToIndex = null;
150   /** case sensitive column name -> index in ResultSet data array */
151   protected transient Hashtable JavaDoc sensitiveNameToIndex = null;
152
153   /** Type of ResultSet */
154   protected int resultSetType = 0;
155   /** Concurrency for this ResultSet */
156   protected int resultSetConcurrency = 0;
157   /** the warning chain */
158   protected BackendDriverException warnings = null;
159   /** warnings associated to the statement that created us */
160   protected SQLWarning JavaDoc statementWarnings = null;
161   /** Statement corresponding to this ResultSet, if any (not for metadata) */
162   protected transient Statement owningStatement;
163   /** The driver connection we were received from. Useful for streaming */
164   private final Connection connection;
165
166   private boolean isClosed = true;
167
168   /** Statement for deleting rows with Updatable ResultSets * */
169   private transient PreparedStatement deleteStatement = null;
170   /** Statement for inserting rows with Updatable ResultSets * */
171   private transient PreparedStatement insertStatement = null;
172   /** Statement for refreshing rows with Updatable ResultSets * */
173   private transient PreparedStatement refreshStatement = null;
174   /** Statement for updating rows with Updatable ResultSets * */
175   private transient PreparedStatement updateStatement = null;
176   /** Indicates whether cursor is on the insert row * */
177   private transient boolean inserting = false;
178   /** Indicates if the current row is being updated * */
179   private transient boolean updating = false;
180   /** Temporary object for not yet comitted ResultSet updates * */
181   private transient Object JavaDoc[] tempRow = null;
182   /** Cache the columns forming the primary key * */
183   private transient String JavaDoc[] primaryKeyColumns = null;
184
185   private static final String JavaDoc UPDATEABLE_MESSAGE = "ResultSet not updateable. The "
186                                                                      + "query that generated this result set must select only one table, and must "
187                                                                      + "select all primary keys from that table. See the JDBC 2.1 API Specification, "
188                                                                      + "section 5.6 for more details.";
189   /**
190    * Hold a reference to the returned stream so we can close it as soon as the
191    * application is no more allowed to use it (per the JDBC spec).
192    */

193   private InputStream JavaDoc currentStream = null;
194
195   // ---------------------------------------------------------------------
196
// Traversal/Positioning
197
// ---------------------------------------------------------------------
198

199   /**
200    * A ResultSet is initially positioned before its first row, the first call to
201    * next makes the first row the current row; the second call makes the second
202    * row the current row, etc.
203    * <p>
204    * If an input stream from the previous row is open, it is implicitly closed.
205    * The ResultSet's warning chain is cleared when a new row is read
206    *
207    * @return <code>true</code> if the new current is valid; <code>false</code>
208    * if there are no more rows
209    * @exception java.sql.SQLException if a database access error occurs
210    */

211   public boolean next() throws java.sql.SQLException JavaDoc
212   {
213     checkIfClosed();
214
215     if (inserting)
216     {
217       insertStatement.clearParameters();
218       tempRow = null;
219       inserting = false;
220     }
221
222     if (updating)
223       cancelRowUpdates();
224
225     if (nbOfRows == 0)
226       return false;
227
228     if (currentRow + 1 >= nbOfRows)
229     {
230       if (hasMoreData)
231       {
232         // TODO: what happens if user closed this connection? What says JDBC?
233
this.connection.tryFetchNext(cursorName, fetchSize);
234         // no SQLException from controller, so let's receive our new rows
235
try
236         {
237           receiveRows();
238         }
239         catch (IOException JavaDoc ioe)
240         {
241           throw new DriverSQLException("I/O Error while fetching new rows:\n"
242               + ioe.getLocalizedMessage(), ioe);
243         }
244         currentRow = 0;
245         if (data == null)
246         {
247           nbOfRows = 0;
248           return false;
249         }
250         else
251         {
252           nbOfRows = data.size();
253           return true;
254         }
255       }
256
257       // force scroll past end
258
currentRow = nbOfRows;
259       return false;
260     }
261
262     clearWarnings();
263     currentRow++;
264     return true;
265   }
266
267   /**
268    * The prev method is not part of JDBC, but because of the architecture of
269    * this driver it is possible to move both forward and backward within the
270    * result set.
271    * <p>
272    * If an input stream from the previous row is open, it is implicitly closed.
273    * The ResultSet's warning chain is cleared when a new row is read
274    *
275    * @return <code>true</code> if the new current is valid; <code>false</code>
276    * if there are no more rows
277    * @exception SQLException if a database access error occurs
278    */

279   public boolean prev() throws SQLException JavaDoc
280   {
281     checkIfClosed();
282
283     if (inserting)
284     {
285       insertStatement.clearParameters();
286       tempRow = null;
287       inserting = false;
288     }
289
290     if (updating)
291       cancelRowUpdates();
292
293     if (currentRow - 1 >= 0)
294     {
295       currentRow--;
296       return true;
297     }
298
299     return false;
300   }
301
302   /**
303    * JDBC 2.0.
304    * <p>
305    * Determine if the cursor is before the first row in the result set.
306    *
307    * @return <code>true</code> if before the first row, <code>false</code>
308    * otherwise. Returns <code>false</code> when the result set
309    * contains no rows.
310    * @exception SQLException if a database-access error occurs.
311    */

312   public boolean isBeforeFirst() throws SQLException JavaDoc
313   {
314     checkIfClosed();
315     if (nbOfRows == 0)
316       return false;
317     else
318       return (currentRow == -1);
319   }
320
321   /**
322    * JDBC 2.0
323    * <p>
324    * Determine if the cursor is after the last row in the result set.
325    *
326    * @return <code>true</code> if after the last row, <code>false</code>
327    * otherwise. Returns <code>false</code> when the result set
328    * contains no rows.
329    * @exception SQLException if a database-access error occurs.
330    */

331   public boolean isAfterLast() throws SQLException JavaDoc
332   {
333     checkIfClosed();
334     if (nbOfRows == 0)
335       return false;
336     else
337       return (currentRow >= nbOfRows);
338   }
339
340   /**
341    * JDBC 2.0
342    * <p>
343    * Determine if the cursor is on the first row of the result set.
344    *
345    * @return <code>true</code> if on the first row, <code>false</code>
346    * otherwise.
347    * @exception SQLException if a database-access error occurs.
348    */

349   public boolean isFirst() throws SQLException JavaDoc
350   {
351     checkIfClosed();
352     if (nbOfRows == 0)
353       return false;
354     else
355       return (currentRow == 0);
356   }
357
358   /**
359    * JDBC 2.0
360    * <p>
361    * Determine if the cursor is on the last row of the result set. Note: Calling
362    * isLast() may be expensive since the JDBC driver might need to fetch ahead
363    * one row in order to determine whether the current row is the last row in
364    * the result set.
365    *
366    * @return <code>true</code> if on the last row, <code>false</code>
367    * otherwise.
368    * @exception SQLException if a database-access error occurs.
369    */

370   public boolean isLast() throws SQLException JavaDoc
371   {
372     checkIfClosed();
373     if (nbOfRows == 0)
374       return false;
375     else
376       return (currentRow == nbOfRows - 1);
377   }
378
379   /**
380    * JDBC 2.0
381    * <p>
382    * Moves to the front of the result set, just before the first row. Has no
383    * effect if the result set contains no rows.
384    *
385    * @exception SQLException if a database-access error occurs, or result set
386    * type is TYPE_FORWARD_ONLY
387    */

388   public void beforeFirst() throws SQLException JavaDoc
389   {
390     checkIfScrollable();
391
392     if (inserting)
393     {
394       insertStatement.clearParameters();
395       tempRow = null;
396       inserting = false;
397     }
398
399     if (updating)
400       cancelRowUpdates();
401
402     currentRow = -1;
403   }
404
405   /**
406    * JDBC 2.0
407    * <p>
408    * Moves to the end of the result set, just after the last row. Has no effect
409    * if the result set contains no rows.
410    *
411    * @exception SQLException if a database-access error occurs, or result set
412    * type is TYPE_FORWARD_ONLY.
413    */

414   public void afterLast() throws SQLException JavaDoc
415   {
416     checkIfScrollable();
417
418     if (inserting)
419     {
420       insertStatement.clearParameters();
421       tempRow = null;
422       inserting = false;
423     }
424
425     if (updating)
426       cancelRowUpdates();
427
428     if (nbOfRows != 0)
429       currentRow = nbOfRows;
430   }
431
432   /**
433    * JDBC 2.0
434    * <p>
435    * Moves to the first row in the result set.
436    *
437    * @return <code>true</code> if on a valid row, false if no rows in the
438    * result set.
439    * @exception SQLException if a database-access error occurs, or result set
440    * type is TYPE_FORWARD_ONLY.
441    */

442   public boolean first() throws SQLException JavaDoc
443   {
444     checkIfScrollable();
445
446     if (inserting)
447     {
448       insertStatement.clearParameters();
449       tempRow = null;
450       inserting = false;
451     }
452
453     if (updating)
454       cancelRowUpdates();
455
456     if (nbOfRows == 0)
457       return false;
458
459     currentRow = 0;
460     return true;
461   }
462
463   /**
464    * JDBC 2.0
465    * <p>
466    * Moves to the last row in the result set.
467    *
468    * @return <code>true</code> if on a valid row, false if no rows in the
469    * result set.
470    * @exception SQLException if a database-access error occurs, or result set
471    * type is TYPE_FORWARD_ONLY.
472    */

473   public boolean last() throws SQLException JavaDoc
474   {
475     checkIfScrollable();
476
477     if (inserting)
478     {
479       insertStatement.clearParameters();
480       tempRow = null;
481       inserting = false;
482     }
483
484     if (updating)
485       cancelRowUpdates();
486
487     if (nbOfRows == 0)
488       return false;
489
490     currentRow = nbOfRows - 1;
491     return true;
492   }
493
494   /**
495    * JDBC 2.0
496    * <p>
497    * Determine the current row number. The first row is number 1, the second
498    * number 2, etc.
499    *
500    * @return the current row number, else return 0 if there is no current row
501    * @exception SQLException if a database-access error occurs.
502    */

503   public int getRow() throws SQLException JavaDoc
504   {
505     checkIfClosed();
506     if (currentRow < 0 || currentRow >= nbOfRows || nbOfRows == 0)
507       return 0;
508     else
509       return currentRow + 1;
510   }
511
512   /**
513    * JDBC 2.0
514    * <p>
515    * Move to an absolute row number in the result set.
516    * <p>
517    * If row is positive, moves to an absolute row with respect to the beginning
518    * of the result set. The first row is row 1, the second is row 2, etc.
519    * <p>
520    * If row is negative, moves to an absolute row position with respect to the
521    * end of result set. For example, calling absolute(-1) positions the cursor
522    * on the last row, absolute(-2) indicates the next-to-last row, etc.
523    * <p>
524    * An attempt to position the cursor beyond the first/last row in the result
525    * set, leaves the cursor before/after the first/last row, respectively.
526    * <p>
527    * Note: Calling absolute(1) is the same as calling first(). Calling
528    * absolute(-1) is the same as calling last().
529    *
530    * @param row the row to move to
531    * @return <code>true</code> if on the result set, false if off.
532    * @exception SQLException if a database-access error occurs, or row is 0, or
533    * result set type is TYPE_FORWARD_ONLY.
534    */

535   public boolean absolute(int row) throws SQLException JavaDoc
536   {
537     checkIfScrollable();
538
539     if (inserting)
540     {
541       insertStatement.clearParameters();
542       tempRow = null;
543       inserting = false;
544     }
545
546     if (updating)
547       cancelRowUpdates();
548
549     if (nbOfRows == 0)
550       return false;
551
552     if (row == 0)
553     {
554       beforeFirst();
555       return false;
556     }
557
558     if (row == 1)
559       return first();
560
561     if (row == -1)
562       return last();
563
564     if (row > nbOfRows)
565     {
566       afterLast();
567       return false;
568     }
569
570     if (row < 0)
571     { // adjust to reflect after end of result set
572
int newRowPosition = nbOfRows + row + 1;
573
574       if (newRowPosition <= 0)
575       {
576         beforeFirst();
577         return false;
578       }
579
580       return absolute(newRowPosition);
581     }
582     else
583     {
584       row--; // adjust for index difference
585
currentRow = row;
586       return true;
587     }
588   }
589
590   /**
591    * JDBC 2.0
592    * <p>
593    * Moves a relative number of rows, either positive or negative. Attempting to
594    * move beyond the first/last row in the result set positions the cursor
595    * before/after the the first/last row. Calling relative(0) is valid, but does
596    * not change the cursor position.
597    * <p>
598    * Note: Calling relative(1) is different than calling next() since is makes
599    * sense to call next() when there is no current row, for example, when the
600    * cursor is positioned before the first row or after the last row of the
601    * result set.
602    *
603    * @param rows the number of rows
604    * @return <code>true</code> if on a row, false otherwise.
605    * @exception SQLException if a database-access error occurs, or there is no
606    * current row, or result set type is TYPE_FORWARD_ONLY.
607    */

608   public boolean relative(int rows) throws SQLException JavaDoc
609   {
610     checkIfScrollable();
611
612     if (inserting)
613     {
614       insertStatement.clearParameters();
615       tempRow = null;
616       inserting = false;
617     }
618
619     if (updating)
620       cancelRowUpdates();
621
622     if (nbOfRows == 0)
623       return false;
624
625     return absolute(currentRow + rows + 1);
626   }
627
628   /**
629    * JDBC 2.0
630    * <p>
631    * Moves to the previous row in the result set.
632    * <p>
633    * Note: previous() is not the same as relative(-1) since it makes sense to
634    * call previous() when there is no current row.
635    *
636    * @return <code>true</code> if on a valid row, false if off the result set.
637    * @exception SQLException if a database-access error occurs, or result set
638    * type is TYPE_FORWAR_DONLY.
639    */

640   public boolean previous() throws SQLException JavaDoc
641   {
642     checkIfScrollable();
643     return prev();
644   }
645
646   /**
647    * JDBC 2.0 Give a hint as to the direction in which the rows in this result
648    * set will be processed. The initial value is determined by the statement
649    * that produced the result set. The fetch direction may be changed at any
650    * time.
651    *
652    * @param direction the fetch direction
653    * @exception SQLException if a database-access error occurs, or the result
654    * set type is TYPE_FORWARD_ONLY and direction is not
655    * FETCH_FORWARD. MM.MySQL actually ignores this, because it has
656    * the whole result set anyway, so the direction is immaterial.
657    */

658   public void setFetchDirection(int direction) throws SQLException JavaDoc
659   {
660     if (direction != FETCH_FORWARD && direction != FETCH_REVERSE)
661       throw new SQLException JavaDoc("Illegal value for fetch direction");
662
663     if (resultSetType == ResultSet.TYPE_FORWARD_ONLY
664         && direction != FETCH_FORWARD)
665       throw new SQLException JavaDoc(
666           "Operation requires a scrollable ResultSet, but this ResultSet is FORWARD_ONLY");
667
668     fetchDirection = direction;
669   }
670
671   /**
672    * JDBC 2.0 Return the fetch direction for this result set.
673    *
674    * @return the fetch direction
675    * @exception SQLException if a database-access error occurs
676    */

677   public int getFetchDirection() throws SQLException JavaDoc
678   {
679     return fetchDirection;
680   }
681
682   /**
683    * See performance issue explained in
684    * {@link org.continuent.sequoia.controller.virtualdatabase.VirtualDatabaseWorkerThread#fetchNextResultSetRows()}
685    *
686    * @param rows the number of rows to fetch
687    * @exception SQLException if a database-access error occurs, or the condition
688    * 0 <= rows <= statement.getMaxRows() is not satisfied.
689    * Currently ignored by this driver.
690    * @see ResultSet#setFetchSize(int)
691    */

692   public void setFetchSize(int rows) throws SQLException JavaDoc
693   {
694     // This is just a hint afterall, let's not try to throw exceptions for
695
// nothing
696
if (rows < 0)
697       throw new SQLException JavaDoc("Value must be between 0 and getMaxRows()");
698
699     fetchSize = rows;
700   }
701
702   /**
703    * JDBC 2.0 Return the fetch size for this result set.
704    *
705    * @return the fetch size
706    * @exception SQLException if a database-access error occurs
707    */

708   public int getFetchSize() throws SQLException JavaDoc
709   {
710     return fetchSize;
711   }
712
713   //
714
// ---------------------------------------------------------------------
715
// Getter's and Setter's
716
// ---------------------------------------------------------------------
717
//
718

719   /**
720    * Get the value of a column in the current row as a Java String
721    *
722    * @param columnIndex the first column is 1, the second is 2...
723    * @return the column value, null for SQL NULL
724    * @exception SQLException if a database access error occurs
725    */

726   public String JavaDoc getString(int columnIndex) throws SQLException JavaDoc
727   {
728     checkRowAndColPosAndSetNullFlag(columnIndex);
729
730     if (wasNullFlag)
731       return null;
732
733     if (inserting || updating)
734       return tempRow[columnIndex - 1].toString();
735     else
736     {
737       Object JavaDoc tmpData = (((Object JavaDoc[]) data.get(currentRow))[columnIndex - 1]);
738       if (tmpData instanceof byte[])
739       {
740         String JavaDoc encoding = this.fields[columnIndex - 1].getEncoding();
741         if (encoding != null)
742           try
743           {
744             return new String JavaDoc((byte[]) tmpData, encoding);
745           }
746           catch (UnsupportedEncodingException JavaDoc e)
747           {
748             throw (SQLException JavaDoc) new SQLException JavaDoc(
749                 "UnsupportedEncodingException (to " + encoding + ") : "
750                     + e.getMessage()).initCause(e);
751           }
752         else
753           return new String JavaDoc((byte[]) tmpData);
754       }
755       return tmpData.toString();
756     }
757   }
758
759   /**
760    * Get the value of a column in the current row as a Java boolean
761    *
762    * @param columnIndex the first column is 1, the second is 2...
763    * @return the column value, false for SQL NULL
764    * @exception SQLException if a database access error occurs
765    */

766   public boolean getBoolean(int columnIndex) throws SQLException JavaDoc
767   {
768     checkRowAndColPosAndSetNullFlag(columnIndex);
769
770     if (wasNullFlag)
771       return false;
772
773     Object JavaDoc object;
774     if (inserting || updating)
775       object = tempRow[columnIndex - 1];
776     else
777       object = (((Object JavaDoc[]) data.get(currentRow))[columnIndex - 1]);
778
779     String JavaDoc stringVal = object.toString();
780     if ((stringVal != null) && (stringVal.length() > 0))
781     {
782       stringVal = stringVal.toLowerCase();
783
784       if ("t".equals(stringVal))
785       {
786         return true;
787       }
788       else if ("f".equals(stringVal))
789       {
790         return false;
791       }
792       else if ("true".equals(stringVal))
793       {
794         return true;
795       }
796       else if ("false".equals(stringVal))
797       {
798         return false;
799       }
800       else if ("1".equals(stringVal))
801       {
802         return true;
803       }
804       else if ("0".equals(stringVal))
805       {
806         return false;
807       }
808       else if ("y".equals(stringVal))
809       {
810         return true;
811       }
812       else if ("n".equals(stringVal))
813       {
814         return false;
815       }
816       else if ("yes".equals(stringVal))
817       {
818         return true;
819       }
820       else if ("no".equals(stringVal))
821       {
822         return false;
823       }
824       else if (object instanceof Number JavaDoc)
825       {
826         int value = ((Number JavaDoc) object).intValue();
827         if (value == 0)
828           return false;
829         else if (value == 1)
830           return true;
831         // else other value throw an exception
832
}
833
834       // we didn't find anything reasonable and throw an exception
835
throw new SQLException JavaDoc("column value " + stringVal + " of type: "
836           + object.getClass() + " could not be converted to boolean");
837     }
838     else
839     {
840       return false;
841     }
842   }
843
844   /**
845    * Get the value of a column in the current row as a Java short.
846    *
847    * @param columnIndex the first column is 1, the second is 2,...
848    * @return the column value; 0 if SQL NULL
849    * @exception SQLException if a database access error occurs
850    */

851   public short getShort(int columnIndex) throws SQLException JavaDoc
852   {
853     checkRowAndColPosAndSetNullFlag(columnIndex);
854
855     if (wasNullFlag)
856       return 0;
857
858     Object JavaDoc obj;
859     if (inserting || updating)
860       obj = tempRow[columnIndex - 1];
861     else
862       obj = ((Object JavaDoc[]) data.get(currentRow))[columnIndex - 1];
863
864     if (obj instanceof Number JavaDoc)
865     {
866       return ((Number JavaDoc) obj).shortValue();
867     }
868
869     // the object is not of type number we parse the string representation
870
try
871     {
872       String JavaDoc string = obj.toString();
873       string = string.trim();
874       return Short.parseShort(string);
875     }
876     catch (NumberFormatException JavaDoc e)
877     {
878       // Try to convert a boolean
879
String JavaDoc string = obj.toString().toLowerCase().trim();
880       if ("true".equals(string))
881         return 1;
882       else if ("false".equals(string))
883         return 0;
884       throw new SQLException JavaDoc("the value " + obj.toString()
885           + " is not a valid short number");
886     }
887   }
888
889   /**
890    * Get the value of a column in the current row as a Java int.
891    *
892    * @param columnIndex the first column is 1, the second is 2,...
893    * @return the column value; 0 if SQL NULL
894    * @exception SQLException if a database access error occurs
895    */

896   public int getInt(int columnIndex) throws SQLException JavaDoc
897   {
898     checkRowAndColPosAndSetNullFlag(columnIndex);
899
900     if (wasNullFlag)
901       return 0;
902
903     Object JavaDoc obj;
904     if (inserting || updating)
905       obj = tempRow[columnIndex - 1];
906     else
907       obj = ((Object JavaDoc[]) data.get(currentRow))[columnIndex - 1];
908
909     if (obj instanceof Number JavaDoc)
910     {
911       return ((Number JavaDoc) obj).intValue();
912     }
913
914     // the object is not of type number we parse the string representation
915
try
916     {
917       String JavaDoc string = obj.toString();
918       string = string.trim();
919       return Integer.parseInt(string);
920     }
921     catch (NumberFormatException JavaDoc e)
922     {
923       // Try to convert a boolean
924
String JavaDoc string = obj.toString().toLowerCase().trim();
925       if ("true".equals(string))
926         return 1;
927       else if ("false".equals(string))
928         return 0;
929       throw new SQLException JavaDoc("the value " + obj.toString()
930           + " is not a valid int number");
931     }
932   }
933
934   /**
935    * Get the value of a column in the current row as a Java long.
936    *
937    * @param columnIndex the first column is 1, the second is 2,...
938    * @return the column value; 0 if SQL NULL
939    * @exception SQLException if a database access error occurs
940    */

941   public long getLong(int columnIndex) throws SQLException JavaDoc
942   {
943     checkRowAndColPosAndSetNullFlag(columnIndex);
944
945     if (wasNullFlag)
946       return 0;
947
948     Object JavaDoc obj;
949     if (inserting || updating)
950       obj = tempRow[columnIndex - 1];
951     else
952       obj = ((Object JavaDoc[]) data.get(currentRow))[columnIndex - 1];
953
954     if (obj instanceof Number JavaDoc)
955     {
956       return ((Number JavaDoc) obj).longValue();
957     }
958
959     // the object is not of type number we parse the string representation
960
try
961     {
962       String JavaDoc string = obj.toString();
963       string = string.trim();
964       return Long.parseLong(string);
965     }
966     catch (NumberFormatException JavaDoc e)
967     {
968       // Try to convert a boolean
969
String JavaDoc string = obj.toString().toLowerCase().trim();
970       if ("true".equals(string))
971         return 1;
972       else if ("false".equals(string))
973         return 0;
974       throw new SQLException JavaDoc("the value " + obj.toString()
975           + " is not a valid long number");
976     }
977   }
978
979   /**
980    * Get the value of a column in the current row as a Java float.
981    *
982    * @param columnIndex the first column is 1, the second is 2,...
983    * @return the column value; 0 if SQL NULL
984    * @exception SQLException if a database access error occurs
985    */

986   public float getFloat(int columnIndex) throws SQLException JavaDoc
987   {
988     checkRowAndColPosAndSetNullFlag(columnIndex);
989
990     if (wasNullFlag)
991       return 0;
992
993     Object JavaDoc obj;
994     if (inserting || updating)
995       obj = tempRow[columnIndex - 1];
996     else
997       obj = ((Object JavaDoc[]) data.get(currentRow))[columnIndex - 1];
998
999     if (obj instanceof Number JavaDoc)
1000    {
1001      return ((Number JavaDoc) obj).floatValue();
1002    }
1003
1004    // the object is not of type number we parse the string representation
1005
try
1006    {
1007      String JavaDoc string = obj.toString();
1008      string = string.trim();
1009      return Float.parseFloat(string);
1010    }
1011    catch (NumberFormatException JavaDoc e)
1012    {
1013      // Try to convert a boolean
1014
String JavaDoc string = obj.toString().toLowerCase().trim();
1015      if ("true".equals(string))
1016        return 1;
1017      else if ("false".equals(string))
1018        return 0;
1019      throw new SQLException JavaDoc("the value " + obj.toString()
1020          + " is not a valid float number");
1021    }
1022  }
1023
1024  /**
1025   * Get the value of a column in the current row as a Java double.
1026   *
1027   * @param columnIndex the first column is 1, the second is 2,...
1028   * @return the column value; 0 if SQL NULL
1029   * @exception SQLException if a database access error occurs
1030   */

1031  public double getDouble(int columnIndex) throws SQLException JavaDoc
1032  {
1033    checkRowAndColPosAndSetNullFlag(columnIndex);
1034
1035    if (wasNullFlag)
1036      return 0;
1037
1038    Object JavaDoc obj;
1039    if (inserting || updating)
1040      obj = tempRow[columnIndex - 1];
1041    else
1042      obj = ((Object JavaDoc[]) data.get(currentRow))[columnIndex - 1];
1043
1044    if (obj instanceof Number JavaDoc)
1045    {
1046      return ((Number JavaDoc) obj).doubleValue();
1047    }
1048
1049    // the object is not of type number we parse the string representation
1050
try
1051    {
1052      String JavaDoc string = obj.toString();
1053      string = string.trim();
1054      return Double.parseDouble(string);
1055    }
1056    catch (NumberFormatException JavaDoc e)
1057    {
1058      // Try to convert a boolean
1059
String JavaDoc string = obj.toString().toLowerCase().trim();
1060      if ("true".equals(string))
1061        return 1;
1062      else if ("false".equals(string))
1063        return 0;
1064      throw new SQLException JavaDoc("the value " + obj.toString()
1065          + " is not a valid double number");
1066    }
1067  }
1068
1069  /**
1070   * Get the value of a column in the current row as a java.lang.BigDecimal
1071   * object
1072   *
1073   * @param columnIndex the first column is 1, the second is 2...
1074   * @param scale the number of digits to the right of the decimal
1075   * @return the column value; if the value is SQL NULL, null
1076   * @exception SQLException if a database access error occurs
1077   * @deprecated
1078   */

1079  public BigDecimal JavaDoc getBigDecimal(int columnIndex, int scale)
1080      throws SQLException JavaDoc
1081  {
1082    BigDecimal JavaDoc bigDecimal = getBigDecimal(columnIndex);
1083    if (bigDecimal == null)
1084      return null;
1085    else
1086      return bigDecimal.setScale(scale);
1087  }
1088
1089  /**
1090   * Get the value of a column in the current row as a Java byte array.
1091   * <p>
1092   * <b>Be warned </b> If the blob is huge, then you may run out of memory.
1093   *
1094   * @param columnIndex the first column is 1, the second is 2, ...
1095   * @return the column value; if the value is SQL NULL, the result is null
1096   * @exception SQLException if a database access error occurs
1097   */

1098  public byte[] getBytes(int columnIndex) throws SQLException JavaDoc
1099  {
1100    checkRowAndColPosAndSetNullFlag(columnIndex);
1101
1102    if (wasNullFlag)
1103      return null;
1104
1105    Object JavaDoc o;
1106    if (inserting || updating)
1107      o = tempRow[columnIndex - 1];
1108    else
1109      o = ((Object JavaDoc[]) data.get(currentRow))[columnIndex - 1];
1110
1111    byte[] maybeEncodedBytes;
1112    if (o instanceof byte[])
1113    {
1114      maybeEncodedBytes = (byte[]) o;
1115    }
1116    else if (o instanceof ByteArrayBlob)
1117    {
1118      ByteArrayBlob b = (ByteArrayBlob) o;
1119      // TODO: use getBinaryStream() to avoid the copy
1120
maybeEncodedBytes = b.getBytes(1, (int) b.length());
1121    }
1122    else
1123    {
1124      throw new NotImplementedException("in getBytes(" + columnIndex
1125          + "), don't know how to convert type " + o.getClass().getName()
1126          + " into a byte array ");
1127    }
1128
1129    return maybeEncodedBytes; // maybe not!
1130
}
1131
1132  /**
1133   * Get the value of a column in the current row as a java.sql.Date object
1134   *
1135   * @param columnIndex the first column is 1, the second is 2...
1136   * @return the column value; null if SQL NULL
1137   * @exception SQLException if a database access error occurs
1138   */

1139  public java.sql.Date JavaDoc getDate(int columnIndex) throws SQLException JavaDoc
1140  {
1141    checkRowAndColPosAndSetNullFlag(columnIndex);
1142
1143    if (wasNullFlag)
1144      return null;
1145
1146    // we may be reading a timestamp column and have to convert it to date
1147
// the client is asking for the date field only, we have to make sure
1148
// hour,minutes,... are cleared
1149
String JavaDoc dateString;
1150    if (inserting || updating)
1151      dateString = tempRow[columnIndex - 1].toString();
1152    else
1153      dateString = ((Object JavaDoc[]) data.get(currentRow))[columnIndex - 1]
1154          .toString();
1155
1156    if (dateString.length() == 10)
1157      return java.sql.Date.valueOf(dateString);
1158    else
1159      return java.sql.Date.valueOf(dateString.substring(0, 10));
1160  }
1161
1162  /**
1163   * Get the value of a column in the current row as a java.sql.Time object
1164   *
1165   * @param columnIndex the first column is 1, the second is 2...
1166   * @return the column value; null if SQL NULL
1167   * @exception SQLException if a database access error occurs
1168   */

1169  public Time JavaDoc getTime(int columnIndex) throws SQLException JavaDoc
1170  {
1171    checkRowAndColPosAndSetNullFlag(columnIndex);
1172
1173    if (wasNullFlag)
1174      return null;
1175
1176    Object JavaDoc obj;
1177    if (inserting || updating)
1178      obj = tempRow[columnIndex - 1];
1179    else
1180      obj = ((Object JavaDoc[]) data.get(currentRow))[columnIndex - 1];
1181
1182    if (obj instanceof java.util.Date JavaDoc)
1183    {
1184      java.util.Date JavaDoc time = (java.util.Date JavaDoc) obj;
1185      // the driver returns the format of the column, but we are asking for
1186
// the time values only.
1187
String JavaDoc timeString = time.toString();
1188      if (timeString.length() == 8)
1189      {
1190        // ok we have got a timefield of the format HH:mm:ss, exactly the way
1191
// we need it, no further processing is required
1192
return new Time JavaDoc(time.getTime());
1193      }
1194
1195      // we have got the date fields too and have to clear the year, month and
1196
// date field
1197
Calendar JavaDoc cal = Calendar.getInstance();
1198      cal.setTime(time);
1199      cal.clear(Calendar.YEAR);
1200      cal.clear(Calendar.MONTH);
1201      cal.clear(Calendar.DATE);
1202      cal.clear(Calendar.MILLISECOND);
1203      return new Time JavaDoc(cal.getTimeInMillis());
1204    }
1205
1206    // the object is not of type date we parse the string representation
1207
try
1208    {
1209      String JavaDoc string = obj.toString();
1210      string = string.trim();
1211      return Time.valueOf(string);
1212    }
1213    catch (IllegalArgumentException JavaDoc e)
1214    {
1215      throw new SQLException JavaDoc("the value " + obj.toString()
1216          + " is not a valid time");
1217    }
1218  }
1219
1220  /**
1221   * Get the value of a column in the current row as a java.sql.Timestamp object
1222   *
1223   * @param columnIndex the first column is 1, the second is 2...
1224   * @return the column value; null if SQL NULL
1225   * @exception SQLException if a database access error occurs
1226   */

1227  public Timestamp JavaDoc getTimestamp(int columnIndex) throws SQLException JavaDoc
1228  {
1229    checkRowAndColPosAndSetNullFlag(columnIndex);
1230
1231    if (wasNullFlag)
1232      return null;
1233
1234    Object JavaDoc obj;
1235    if (inserting || updating)
1236      obj = tempRow[columnIndex - 1];
1237    else
1238      obj = ((Object JavaDoc[]) data.get(currentRow))[columnIndex - 1];
1239
1240    if (obj instanceof java.util.Date JavaDoc)
1241    {
1242      return new Timestamp JavaDoc(((java.util.Date JavaDoc) obj).getTime());
1243    }
1244
1245    // the object is not of type timestamp we parse the string representation
1246
try
1247    {
1248      String JavaDoc string = obj.toString();
1249      string = string.trim();
1250      return Timestamp.valueOf(string);
1251    }
1252    catch (IllegalArgumentException JavaDoc e)
1253    {
1254      throw new SQLException JavaDoc("the value " + obj.toString()
1255          + " is not a valid timestamp");
1256    }
1257  }
1258
1259  /**
1260   * A column value can be retrieved as a stream of ASCII characters and then
1261   * read in chunks from the stream. This method is particulary suitable for
1262   * retrieving large LONGVARCHAR values. The JDBC driver will do any necessary
1263   * conversion from the database format into ASCII.
1264   * <p>
1265   * <B>Note: </B> All the data in the returned stream must be read prior to
1266   * getting the value of any other column. The next call to a get method
1267   * implicitly closes the stream. Also, a stream may return 0 for available()
1268   * whether there is data available or not.
1269   *
1270   * @param columnIndex the first column is 1, the second is 2, ...
1271   * @return a Java InputStream that delivers the database column value as a
1272   * stream of one byte ASCII characters. If the value is SQL NULL then
1273   * the result is null
1274   * @exception SQLException if a database access error occurs
1275   * @see #getBinaryStream(int)
1276   */

1277  public InputStream JavaDoc getAsciiStream(int columnIndex) throws SQLException JavaDoc
1278  {
1279    checkRowAndColPosAndSetNullFlag(columnIndex);
1280
1281    try
1282    { // TODO: actually implement a "streaming" encoding instead of encoding
1283
// everything at once. See SEQUOIA-400
1284
currentStream = new ByteArrayInputStream JavaDoc(Charset.forName("US-ASCII")
1285          .newEncoder().encode(CharBuffer.wrap(getString(columnIndex))).array());
1286    }
1287    catch (CharacterCodingException JavaDoc e)
1288    {
1289      throw (SQLException JavaDoc) new SQLException JavaDoc(
1290          "Caught CharacterCodingException (data is probably not ASCII): "
1291              + e.getMessage()).initCause(e);
1292    }
1293    return currentStream;
1294  }
1295
1296  /**
1297   * A column value can also be retrieved as a stream of Unicode characters. We
1298   * implement this as a binary stream.
1299   *
1300   * @param columnIndex the first column is 1, the second is 2...
1301   * @return a Java InputStream that delivers the database column value as a
1302   * stream of two byte Unicode characters. If the value is SQL NULL,
1303   * then the result is null
1304   * @exception SQLException if a database access error occurs
1305   * @deprecated
1306   * @see #getAsciiStream
1307   * @see #getBinaryStream(int)
1308   */

1309  public InputStream JavaDoc getUnicodeStream(int columnIndex) throws SQLException JavaDoc
1310  {
1311    checkRowAndColPosAndSetNullFlag(columnIndex);
1312
1313    currentStream = new ByteArrayInputStream JavaDoc(getString(columnIndex).getBytes());
1314    return currentStream;
1315  }
1316
1317  /**
1318   * A column value can also be retrieved as a binary strea. This method is
1319   * suitable for retrieving LONGVARBINARY values.
1320   *
1321   * @param columnIndex the first column is 1, the second is 2...
1322   * @return a Java InputStream that delivers the database column value as a
1323   * stream of bytes. If the value is SQL NULL, then the result is null
1324   * @exception SQLException if a database access error occurs
1325   * @see #getAsciiStream(int)
1326   * @see #getUnicodeStream(int)
1327   */

1328
1329  public InputStream JavaDoc getBinaryStream(int columnIndex) throws SQLException JavaDoc
1330  {
1331    checkRowAndColPosAndSetNullFlag(columnIndex);
1332
1333    byte[] b = getBytes(columnIndex);
1334    if (b != null)
1335    {
1336      currentStream = new ByteArrayInputStream JavaDoc(b);
1337      return currentStream;
1338    }
1339    else
1340      return null; // SQL NULL
1341
}
1342
1343  /**
1344   * The following routines simply convert the columnName into a columnIndex and
1345   * then call the appropriate routine above.
1346   *
1347   * @param columnName is the SQL name of the column
1348   * @return the column value
1349   * @exception SQLException if a database access error occurs
1350   */

1351  public String JavaDoc getString(String JavaDoc columnName) throws SQLException JavaDoc
1352  {
1353    return this.getString(findColumn(columnName));
1354  }
1355
1356  /**
1357   * @see java.sql.ResultSet#getBoolean(java.lang.String)
1358   */

1359  public boolean getBoolean(String JavaDoc columnName) throws SQLException JavaDoc
1360  {
1361    return getBoolean(findColumn(columnName));
1362  }
1363
1364  /**
1365   * @see java.sql.ResultSet#getByte(java.lang.String)
1366   */

1367  public byte getByte(String JavaDoc columnName) throws SQLException JavaDoc
1368  {
1369    return getByte(findColumn(columnName));
1370  }
1371
1372  /**
1373   * @see java.sql.ResultSet#getShort(java.lang.String)
1374   */

1375  public short getShort(String JavaDoc columnName) throws SQLException JavaDoc
1376  {
1377    return getShort(findColumn(columnName));
1378  }
1379
1380  /**
1381   * @see java.sql.ResultSet#getInt(java.lang.String)
1382   */

1383  public int getInt(String JavaDoc columnName) throws SQLException JavaDoc
1384  {
1385    return getInt(findColumn(columnName));
1386  }
1387
1388  /**
1389   * @see java.sql.ResultSet#getLong(java.lang.String)
1390   */

1391  public long getLong(String JavaDoc columnName) throws SQLException JavaDoc
1392  {
1393    return getLong(findColumn(columnName));
1394  }
1395
1396  /**
1397   * @see java.sql.ResultSet#getFloat(java.lang.String)
1398   */

1399  public float getFloat(String JavaDoc columnName) throws SQLException JavaDoc
1400  {
1401    return getFloat(findColumn(columnName));
1402  }
1403
1404  /**
1405   * @see java.sql.ResultSet#getDouble(java.lang.String)
1406   */

1407  public double getDouble(String JavaDoc columnName) throws SQLException JavaDoc
1408  {
1409    return getDouble(findColumn(columnName));
1410  }
1411
1412  /**
1413   * @see java.sql.ResultSet#getBigDecimal(String, int)
1414   * @deprecated
1415   */

1416  public BigDecimal JavaDoc getBigDecimal(String JavaDoc columnName, int scale)
1417      throws SQLException JavaDoc
1418  {
1419    return getBigDecimal(findColumn(columnName), scale);
1420  }
1421
1422  /**
1423   * @see java.sql.ResultSet#getBytes(java.lang.String)
1424   */

1425  public byte[] getBytes(String JavaDoc columnName) throws SQLException JavaDoc
1426  {
1427    return getBytes(findColumn(columnName));
1428  }
1429
1430  /**
1431   * @see java.sql.ResultSet#getDate(java.lang.String)
1432   */

1433  public java.sql.Date JavaDoc getDate(String JavaDoc columnName) throws SQLException JavaDoc
1434  {
1435    return getDate(findColumn(columnName));
1436  }
1437
1438  /**
1439   * @see java.sql.ResultSet#getTime(java.lang.String)
1440   */

1441  public Time JavaDoc getTime(String JavaDoc columnName) throws SQLException JavaDoc
1442  {
1443    return getTime(findColumn(columnName));
1444  }
1445
1446  /**
1447   * @see java.sql.ResultSet#getTimestamp(java.lang.String)
1448   */

1449  public Timestamp JavaDoc getTimestamp(String JavaDoc columnName) throws SQLException JavaDoc
1450  {
1451    return getTimestamp(findColumn(columnName));
1452  }
1453
1454  /**
1455   * @see java.sql.ResultSet#getAsciiStream(java.lang.String)
1456   */

1457  public InputStream JavaDoc getAsciiStream(String JavaDoc columnName) throws SQLException JavaDoc
1458  {
1459    return getAsciiStream(findColumn(columnName));
1460  }
1461
1462  /**
1463   * @see java.sql.ResultSet#getUnicodeStream(String)
1464   * @deprecated
1465   */

1466  public InputStream JavaDoc getUnicodeStream(String JavaDoc columnName) throws SQLException JavaDoc
1467  {
1468    return getUnicodeStream(findColumn(columnName));
1469  }
1470
1471  /**
1472   * @see java.sql.ResultSet#getBinaryStream(java.lang.String)
1473   */

1474  public InputStream JavaDoc getBinaryStream(String JavaDoc columnName) throws SQLException JavaDoc
1475  {
1476    return getBinaryStream(findColumn(columnName));
1477  }
1478
1479  /**
1480   * The first warning reported by calls on this ResultSet is returned.
1481   * Subsequent ResultSet warnings will be chained to this java.sql.SQLWarning.
1482   * <p>
1483   * The warning chain is automatically cleared each time a new row is read.
1484   * <p>
1485   * <B>Note: </B> This warning chain only covers warnings caused by ResultSet
1486   * methods. Any warnings caused by statement methods (such as reading OUT
1487   * parameters) will be chained on the Statement object.
1488   *
1489   * @return the first java.sql.SQLWarning or null;
1490   * @exception SQLException if a database access error occurs or this method is
1491   * called on a closed result set
1492   */

1493  public java.sql.SQLWarning JavaDoc getWarnings() throws SQLException JavaDoc
1494  {
1495    checkIfClosed();
1496    return connection.convertToSQLWarnings(warnings);
1497  }
1498
1499  /**
1500   * After this call, getWarnings returns null until a new warning is reported
1501   * for this ResultSet
1502   *
1503   * @exception SQLException if a database access error occurs
1504   */

1505
1506  public void clearWarnings() throws SQLException JavaDoc
1507  {
1508    warnings = null;
1509  }
1510
1511  SQLWarning JavaDoc getStatementWarnings()
1512  {
1513    return statementWarnings;
1514  }
1515
1516  void setStatementWarnings(SQLWarning JavaDoc sqlw)
1517  {
1518    statementWarnings = sqlw;
1519  }
1520
1521  /**
1522   * @see java.sql.ResultSet#getCursorName()
1523   */

1524  public String JavaDoc getCursorName() throws SQLException JavaDoc
1525  {
1526    return cursorName;
1527  }
1528
1529  /**
1530   * Get the value of a column in the current row as a Java object
1531   * <p>
1532   * This method will return the value of the given column as a Java object. The
1533   * type of the Java object will be the default Java Object type corresponding
1534   * to the column's SQL type, following the mapping specified in the JDBC
1535   * specification.
1536   * <p>
1537   * This method may also be used to read database specific abstract data types.
1538   *
1539   * @param columnIndex the first column is 1, the second is 2...
1540   * @return a Object holding the column value
1541   * @exception SQLException if a database access error occurs
1542   */

1543  public Object JavaDoc getObject(int columnIndex) throws SQLException JavaDoc
1544  {
1545    checkRowAndColPosAndSetNullFlag(columnIndex);
1546
1547    if (wasNullFlag)
1548      return null;
1549
1550    Object JavaDoc o;
1551    if (inserting || updating)
1552      o = tempRow[columnIndex];
1553    else
1554      o = ((Object JavaDoc[]) data.get(currentRow))[columnIndex - 1];
1555    return o;
1556  }
1557
1558  /**
1559   * Get the value of a column in the current row as a Java object
1560   * <p>
1561   * This method will return the value of the given column as a Java object. The
1562   * type of the Java object will be the default Java Object type corresponding
1563   * to the column's SQL type, following the mapping specified in the JDBC
1564   * specification.
1565   * <p>
1566   * This method may also be used to read database specific abstract data types.
1567   *
1568   * @param columnName is the SQL name of the column
1569   * @return a Object holding the column value
1570   * @exception SQLException if a database access error occurs
1571   */

1572  public Object JavaDoc getObject(String JavaDoc columnName) throws SQLException JavaDoc
1573  {
1574    return getObject(findColumn(columnName));
1575  }
1576
1577  // --------------------------JDBC 2.0-----------------------------------
1578

1579  /**
1580   * @see java.sql.ResultSet#getCharacterStream(int)
1581   */

1582  public java.io.Reader JavaDoc getCharacterStream(int columnIndex) throws SQLException JavaDoc
1583  {
1584    String JavaDoc s = getString(columnIndex);
1585    if (s == null)
1586      return null;
1587    char[] content = s.toCharArray();
1588    return new java.io.CharArrayReader JavaDoc(content);
1589  }
1590
1591  /**
1592   * @see java.sql.ResultSet#getCharacterStream(java.lang.String)
1593   */

1594  public java.io.Reader JavaDoc getCharacterStream(String JavaDoc columnName)
1595      throws SQLException JavaDoc
1596  {
1597    return getCharacterStream(findColumn(columnName));
1598  }
1599
1600  /**
1601   * JDBC 2.0 Get the value of a column in the current row as a
1602   * java.math.BigDecimal object.
1603   *
1604   * @param columnIndex the first column is 1, the second is 2, ...
1605   * @return the column value (full precision); if the value is SQL NULL, the
1606   * result is null
1607   * @exception SQLException if a database-access error occurs.
1608   */

1609  public BigDecimal JavaDoc getBigDecimal(int columnIndex) throws SQLException JavaDoc
1610  {
1611    checkRowAndColPosAndSetNullFlag(columnIndex);
1612
1613    if (wasNullFlag)
1614      return null;
1615
1616    Object JavaDoc obj;
1617    if (inserting || updating)
1618      obj = tempRow[columnIndex - 1];
1619    else
1620      obj = ((Object JavaDoc[]) data.get(currentRow))[columnIndex - 1];
1621
1622    if (obj instanceof BigDecimal JavaDoc)
1623      return (BigDecimal JavaDoc) obj;
1624    else if (obj instanceof Long JavaDoc)
1625    {
1626      return new BigDecimal JavaDoc(((Long JavaDoc) obj).longValue());
1627    }
1628    else if (obj instanceof BigInteger JavaDoc)
1629    {
1630      return new BigDecimal JavaDoc(((BigInteger JavaDoc) obj));
1631    }
1632    else if (obj instanceof Short JavaDoc)
1633    {
1634      return new BigDecimal JavaDoc(((Short JavaDoc) obj).shortValue());
1635    }
1636    else if (obj instanceof Integer JavaDoc)
1637    {
1638      return new BigDecimal JavaDoc(((Integer JavaDoc) obj).intValue());
1639    }
1640    else if (obj instanceof String JavaDoc)
1641    {
1642      return new BigDecimal JavaDoc((String JavaDoc) obj);
1643    }
1644    else if (obj instanceof Number JavaDoc)
1645    {
1646      // float and double have to be converted via string
1647
// othwerwise we produce errors
1648
// javadoc for BigDecimal :
1649
// Note: the results of this constructor can be somewhat unpredictable.
1650
// One might assume that new BigDecimal(.1) is exactly equal to .1, but
1651
// it is actually equal to
1652
// .1000000000000000055511151231257827021181583404541015625. This is so
1653
// because .1 cannot be represented exactly as a double (or, for that
1654
// matter, as a binary fraction of any finite length). Thus, the long
1655
// value that is being passed in to the constructor is not exactly equal
1656
// to .1, appearances nonwithstanding.
1657

1658      // The (String) constructor, on the other hand, is perfectly
1659
// predictable: new BigDecimal(".1") is exactly equal to .1, as one
1660
// would expect. Therefore, it is generally recommended that the
1661
// (String) constructor be used in preference to this one.
1662
return new BigDecimal JavaDoc(obj.toString());
1663    }
1664    else if (obj instanceof Boolean JavaDoc)
1665    {
1666      // Try to convert a boolean
1667
String JavaDoc string = obj.toString().toLowerCase().trim();
1668      if ("true".equals(string))
1669        return new BigDecimal JavaDoc(1);
1670      else if ("false".equals(string))
1671        return new BigDecimal JavaDoc(0);
1672      throw new SQLException JavaDoc("Type " + obj.getClass().getName()
1673          + " is not compatible with BigDecimal");
1674
1675    }
1676    else
1677    {
1678      throw new SQLException JavaDoc("Type " + obj.getClass().getName()
1679          + " is not compatible with BigDecimal");
1680    }
1681  }
1682
1683  /**
1684   * @see java.sql.ResultSet#getBigDecimal(java.lang.String)
1685   */

1686  public BigDecimal JavaDoc getBigDecimal(String JavaDoc columnName) throws SQLException JavaDoc
1687  {
1688    return getBigDecimal(findColumn(columnName));
1689  }
1690
1691  /**
1692   * JDBC 2.0 Returns the value of column as a Java object. Use the map to
1693   * determine the class from which to construct data of SQL structured and
1694   * distinct types.
1695   *
1696   * @param i the first column is 1, the second is 2, ...
1697   * @param map the mapping from SQL type names to Java classes
1698   * @return an object representing the SQL value
1699   * @exception SQLException if a database-access error occurs.
1700   */

1701  public Object JavaDoc getObject(int i, java.util.Map JavaDoc map) throws SQLException JavaDoc
1702  {
1703    throw new NotImplementedException("getObject(int, java.util.Map)");
1704  }
1705
1706  /**
1707   * JDBC 2.0 Get a REF(&lt;structured-type&gt;) column.
1708   *
1709   * @param i the first column is 1, the second is 2, ...
1710   * @return an object representing data of an SQL REF type
1711   * @exception SQLException if a database-access error occurs.
1712   */

1713  public java.sql.Ref JavaDoc getRef(int i) throws SQLException JavaDoc
1714  {
1715    checkRowAndColPosAndSetNullFlag(i);
1716
1717    if (wasNullFlag)
1718      return null;
1719
1720    if (inserting || updating)
1721      return (Ref JavaDoc) tempRow[i - 1];
1722    else
1723      return (Ref JavaDoc) (((Object JavaDoc[]) data.get(currentRow))[i - 1]);
1724  }
1725
1726  /**
1727   * JDBC 2.0 Gets a BLOB column.
1728   *
1729   * @param columnIndex the first column is 1, the second is 2, ...
1730   * @return an object representing a BLOB
1731   * @exception SQLException if a database-access error occurs.
1732   */

1733  public java.sql.Blob JavaDoc getBlob(int columnIndex) throws SQLException JavaDoc
1734  {
1735    checkRowAndColPosAndSetNullFlag(columnIndex);
1736
1737    if (wasNullFlag)
1738      return null;
1739
1740    Object JavaDoc o;
1741    if (inserting || updating)
1742      o = tempRow[columnIndex - 1];
1743    else
1744      o = (((Object JavaDoc[]) data.get(currentRow))[columnIndex - 1]);
1745
1746    // getBytes() does decode
1747
if (o instanceof ByteArrayBlob || o instanceof byte[])
1748      return new ByteArrayBlob(getBytes(columnIndex));
1749    else
1750      throw new NotImplementedException("in getBlob(" + columnIndex
1751          + "), don't know how to convert type " + o.getClass().getName()
1752          + " into a Blob");
1753  }
1754
1755  /**
1756   * JDBC 2.0 Gets a CLOB column.
1757   *
1758   * @param columnIndex the first column is 1, the second is 2, ...
1759   * @return an object representing a CLOB
1760   * @exception SQLException if a database-access error occurs.
1761   */

1762  public java.sql.Clob JavaDoc getClob(int columnIndex) throws SQLException JavaDoc
1763  {
1764    checkRowAndColPosAndSetNullFlag(columnIndex);
1765
1766    if (wasNullFlag)
1767      return null;
1768
1769    Object JavaDoc o;
1770    if (inserting || updating)
1771      o = tempRow[columnIndex - 1];
1772    else
1773      o = (((Object JavaDoc[]) data.get(currentRow))[columnIndex - 1]);
1774
1775    // Test if the type of the Clob is indeed a Clob or just a String
1776
// throw new SQLException("Class:"+o.getClass());
1777
if (o instanceof String JavaDoc)
1778      return new StringClob((String JavaDoc) o);
1779    else if (o instanceof Clob JavaDoc)
1780      return (java.sql.Clob JavaDoc) o;
1781    else
1782      // FIXME: Huh? What it is the purpose of this?
1783
return new StringClob(new String JavaDoc(o.toString()));
1784  }
1785
1786  /**
1787   * JDBC 2.0 Gets an array column.
1788   *
1789   * @param columnIndex the first column is 1, the second is 2, ...
1790   * @return an object representing an SQL array
1791   * @exception SQLException if a database-access error occurs.
1792   */

1793  public java.sql.Array JavaDoc getArray(int columnIndex) throws SQLException JavaDoc
1794  {
1795    checkRowAndColPosAndSetNullFlag(columnIndex);
1796
1797    if (wasNullFlag)
1798      return null;
1799
1800    if (inserting || updating)
1801      return (java.sql.Array JavaDoc) tempRow[columnIndex - 1];
1802    else
1803      return (java.sql.Array JavaDoc) (((Object JavaDoc[]) data.get(currentRow))[columnIndex - 1]);
1804  }
1805
1806  /**
1807   * JDBC 2.0 Returns the value of column as a Java object. Use the map to
1808   * determine the class from which to construct data of SQL structured and
1809   * distinct types.
1810   *
1811   * @param colName the column name
1812   * @param map the mapping from SQL type names to Java classes
1813   * @return an object representing the SQL value
1814   * @exception SQLException if a database-access error occurs.
1815   */

1816  public Object JavaDoc getObject(String JavaDoc colName, java.util.Map JavaDoc map)
1817      throws SQLException JavaDoc
1818  {
1819    return getObject(findColumn(colName), map);
1820  }
1821
1822  /**
1823   * JDBC 2.0 Get a REF(&lt;structured-type&gt;) column.
1824   *
1825   * @param colName the column name
1826   * @return an object representing data of an SQL REF type
1827   * @exception SQLException if a database-access error occurs.
1828   */

1829  public java.sql.Ref JavaDoc getRef(String JavaDoc colName) throws SQLException JavaDoc
1830  {
1831    return getRef(findColumn(colName));
1832  }
1833
1834  /**
1835   * JDBC 2.0 Get a BLOB column.
1836   *
1837   * @param colName the column name
1838   * @return an object representing a BLOB
1839   * @exception SQLException if a database-access error occurs.
1840   */

1841  public java.sql.Blob JavaDoc getBlob(String JavaDoc colName) throws SQLException JavaDoc
1842  {
1843    return getBlob(findColumn(colName));
1844  }
1845
1846  /**
1847   * JDBC 2.0 Get a CLOB column.
1848   *
1849   * @param colName the column name
1850   * @return an object representing a CLOB
1851   * @exception SQLException if a database-access error occurs.
1852   */

1853  public java.sql.Clob JavaDoc getClob(String JavaDoc colName) throws SQLException JavaDoc
1854  {
1855    return getClob(findColumn(colName));
1856  }
1857
1858  /**
1859   * JDBC 2.0 Get an array column.
1860   *
1861   * @param colName the column name
1862   * @return an object representing an SQL array
1863   * @exception SQLException if a database-access error occurs.
1864   */

1865  public java.sql.Array JavaDoc getArray(String JavaDoc colName) throws SQLException JavaDoc
1866  {
1867    return getArray(findColumn(colName));
1868  }
1869
1870  /**
1871   * JDBC 2.0 Get the value of a column in the current row as a java.sql.Date
1872   * object. Use the calendar to construct an appropriate millisecond value for
1873   * the Date, if the underlying database doesn't store timezone information.
1874   *
1875   * @param columnIndex the first column is 1, the second is 2, ...
1876   * @param cal the calendar to use in constructing the date (ignored)
1877   * @return the column value; if the value is SQL NULL, the result is null
1878   * @exception SQLException if a database-access error occurs.
1879   */

1880  public java.sql.Date JavaDoc getDate(int columnIndex, Calendar JavaDoc cal)
1881      throws SQLException JavaDoc
1882  {
1883    return getDate(columnIndex);
1884  }
1885
1886  /**
1887   * Get the value of a column in the current row as a java.sql.Date object. Use
1888   * the calendar to construct an appropriate millisecond value for the Date, if
1889   * the underlying database doesn't store timezone information.
1890   *
1891   * @param columnName is the SQL name of the column
1892   * @param cal the calendar to use in constructing the date
1893   * @return the column value; if the value is SQL NULL, the result is null
1894   * @exception SQLException if a database-access error occurs.
1895   */

1896  public java.sql.Date JavaDoc getDate(String JavaDoc columnName, Calendar JavaDoc cal)
1897      throws SQLException JavaDoc
1898  {
1899    return getDate(findColumn(columnName), cal);
1900  }
1901
1902  /**
1903   * Get the value of a column in the current row as a java.sql.Time object. Use
1904   * the calendar to construct an appropriate millisecond value for the Time, if
1905   * the underlying database doesn't store timezone information.
1906   *
1907   * @param columnIndex the first column is 1, the second is 2, ...
1908   * @param cal the calendar to use in constructing the time
1909   * @return the column value; if the value is SQL NULL, the result is null
1910   * @exception SQLException if a database-access error occurs.
1911   */

1912  public java.sql.Time JavaDoc getTime(int columnIndex, Calendar JavaDoc cal)
1913      throws SQLException JavaDoc
1914  {
1915    return getTime(columnIndex);
1916  }
1917
1918  /**
1919   * Get the value of a column in the current row as a java.sql.Time object. Use
1920   * the calendar to construct an appropriate millisecond value for the Time, if
1921   * the underlying database doesn't store timezone information.
1922   *
1923   * @param columnName is the SQL name of the column
1924   * @param cal the calendar to use in constructing the time
1925   * @return the column value; if the value is SQL NULL, the result is null
1926   * @exception SQLException if a database-access error occurs.
1927   */

1928  public java.sql.Time JavaDoc getTime(String JavaDoc columnName, Calendar JavaDoc cal)
1929      throws SQLException JavaDoc
1930  {
1931    return getTime(findColumn(columnName), cal);
1932  }
1933
1934  /**
1935   * Get the value of a column in the current row as a java.sql.Timestamp
1936   * object. Use the calendar to construct an appropriate millisecond value for
1937   * the Timestamp, if the underlying database doesn't store timezone
1938   * information.
1939   *
1940   * @param columnIndex the first column is 1, the second is 2, ...
1941   * @param cal the calendar to use in constructing the timestamp (ignored)
1942   * @return the column value; if the value is SQL NULL, the result is null
1943   * @exception SQLException if a database-access error occurs.
1944   */

1945  public java.sql.Timestamp JavaDoc getTimestamp(int columnIndex, Calendar JavaDoc cal)
1946      throws SQLException JavaDoc
1947  {
1948    return getTimestamp(columnIndex);
1949  }
1950
1951  /**
1952   * Get the value of a column in the current row as a java.sql.Timestamp
1953   * object. Use the calendar to construct an appropriate millisecond value for
1954   * the Timestamp, if the underlying database doesn't store timezone
1955   * information.
1956   *
1957   * @param columnName is the SQL name of the column
1958   * @param cal the calendar to use in constructing the timestamp
1959   * @return the column value; if the value is SQL NULL, the result is null
1960   * @exception SQLException if a database-access error occurs.
1961   */

1962  public java.sql.Timestamp JavaDoc getTimestamp(String JavaDoc columnName, Calendar JavaDoc cal)
1963      throws SQLException JavaDoc
1964  {
1965    return getTimestamp(findColumn(columnName), cal);
1966  }
1967
1968  // ---------------------------------------------------------------------
1969
// Updates
1970
// ---------------------------------------------------------------------
1971

1972  /**
1973   * JDBC 2.0 Determine if the current row has been updated. The value returned
1974   * depends on whether or not the result set can detect updates.
1975   *
1976   * @return <code>true</code> if the row has been visibly updated by the
1977   * owner or another, and updates are detected
1978   * @exception SQLException if a database-access error occurs
1979   * @see DatabaseMetaData#updatesAreDetected
1980   */

1981  public boolean rowUpdated() throws SQLException JavaDoc
1982  {
1983    throw new NotImplementedException("rowUpdated");
1984  }
1985
1986  /**
1987   * JDBC 2.0 Determine if the current row has been inserted. The value returned
1988   * depends on whether or not the result set can detect visible inserts.
1989   *
1990   * @return <code>true</code> if inserted and inserts are detected
1991   * @exception SQLException if a database-access error occurs
1992   * @see DatabaseMetaData#insertsAreDetected
1993   */

1994  public boolean rowInserted() throws SQLException JavaDoc
1995  {
1996    throw new NotImplementedException("rowInserted");
1997  }
1998
1999  /**
2000   * JDBC 2.0 Determine if this row has been deleted. A deleted row may leave a
2001   * visible "hole" in a result set. This method can be used to detect holes in
2002   * a result set. The value returned depends on whether or not the result set
2003   * can detect deletions.
2004   *
2005   * @return <code>true</code> if deleted and deletes are detected
2006   * @exception SQLException if a database-access error occurs
2007   * @see DatabaseMetaData#deletesAreDetected
2008   */

2009  public boolean rowDeleted() throws SQLException JavaDoc
2010  {
2011    throw new NotImplementedException("rowDeleted");
2012  }
2013
2014  /**
2015   * JDBC 2.0 Give a nullable column a null value. The updateXXX() methods are
2016   * used to update column values in the current row, or the insert row. The
2017   * updateXXX() methods do not update the underlying database, instead the
2018   * updateRow() or insertRow() methods are called to update the database.
2019   *
2020   * @param columnIndex the first column is 1, the second is 2, ...
2021   * @exception SQLException if a database-access error occurs
2022   */

2023  public void updateNull(int columnIndex) throws SQLException JavaDoc
2024  {
2025    checkIfClosed();
2026
2027    if (inserting)
2028      insertStatement
2029          .setNull(columnIndex, fields[columnIndex - 1].getSqlType());
2030    else
2031    {
2032      checkUpdateFlagAndPrepareUpdateIfNeeded();
2033      updateStatement
2034          .setNull(columnIndex, fields[columnIndex - 1].getSqlType());
2035    }
2036
2037    tempRow[columnIndex - 1] = null;
2038  }
2039
2040  /**
2041   * JDBC 2.0 Update a column with a boolean value. The updateXXX() methods are
2042   * used to update column values in the current row, or the insert row. The
2043   * updateXXX() methods do not update the underlying database, instead the
2044   * updateRow() or insertRow() methods are called to update the database.
2045   *
2046   * @param columnIndex the first column is 1, the second is 2, ...
2047   * @param x the new column value
2048   * @exception SQLException if a database-access error occurs
2049   */

2050
2051  public void updateBoolean(int columnIndex, boolean x) throws SQLException JavaDoc
2052  {
2053    checkIfClosed();
2054
2055    if (inserting)
2056      insertStatement.setBoolean(columnIndex, x);
2057    else
2058    {
2059      checkUpdateFlagAndPrepareUpdateIfNeeded();
2060      updateStatement.setBoolean(columnIndex, x);
2061    }
2062
2063    tempRow[columnIndex - 1] = Boolean.valueOf(x);
2064  }
2065
2066  /**
2067   * JDBC 2.0 Update a column with a byte value. The updateXXX() methods are
2068   * used to update column values in the current row, or the insert row. The
2069   * updateXXX() methods do not update the underlying database, instead the
2070   * updateRow() or insertRow() methods are called to update the database.
2071   *
2072   * @param columnIndex the first column is 1, the second is 2, ...
2073   * @param x the new column value
2074   * @exception SQLException if a database-access error occurs
2075   */

2076  public void updateByte(int columnIndex, byte x) throws SQLException JavaDoc
2077  {
2078    checkIfClosed();
2079
2080    if (inserting)
2081      insertStatement.setByte(columnIndex, x);
2082    else
2083    {
2084      checkUpdateFlagAndPrepareUpdateIfNeeded();
2085      updateStatement.setByte(columnIndex, x);
2086    }
2087
2088    tempRow[columnIndex - 1] = new Byte JavaDoc(x);
2089  }
2090
2091  /**
2092   * JDBC 2.0 Update a column with a short value. The updateXXX() methods are
2093   * used to update column values in the current row, or the insert row. The
2094   * updateXXX() methods do not update the underlying database, instead the
2095   * updateRow() or insertRow() methods are called to update the database.
2096   *
2097   * @param columnIndex the first column is 1, the second is 2, ...
2098   * @param x the new column value
2099   * @exception SQLException if a database-access error occurs
2100   */

2101  public void updateShort(int columnIndex, short x) throws SQLException JavaDoc
2102  {
2103    checkIfClosed();
2104
2105    if (inserting)
2106      insertStatement.setShort(columnIndex, x);
2107    else
2108    {
2109      checkUpdateFlagAndPrepareUpdateIfNeeded();
2110      updateStatement.setShort(columnIndex, x);
2111    }
2112
2113    tempRow[columnIndex - 1] = new Short JavaDoc(x);
2114  }
2115
2116  /**
2117   * JDBC 2.0 Update a column with an integer value. The updateXXX() methods are
2118   * used to update column values in the current row, or the insert row. The
2119   * updateXXX() methods do not update the underlying database, instead the
2120   * updateRow() or insertRow() methods are called to update the database.
2121   *
2122   * @param columnIndex the first column is 1, the second is 2, ...
2123   * @param x the new column value
2124   * @exception SQLException if a database-access error occurs
2125   */

2126  public void updateInt(int columnIndex, int x) throws SQLException JavaDoc
2127  {
2128    checkIfClosed();
2129
2130    if (inserting)
2131      insertStatement.setInt(columnIndex, x);
2132    else
2133    {
2134      checkUpdateFlagAndPrepareUpdateIfNeeded();
2135      updateStatement.setInt(columnIndex, x);
2136    }
2137
2138    tempRow[columnIndex - 1] = new Integer JavaDoc(x);
2139  }
2140
2141  /**
2142   * JDBC 2.0 Update a column with a long value. The updateXXX() methods are
2143   * used to update column values in the current row, or the insert row. The
2144   * updateXXX() methods do not update the underlying database, instead the
2145   * updateRow() or insertRow() methods are called to update the database.
2146   *
2147   * @param columnIndex the first column is 1, the second is 2, ...
2148   * @param x the new column value
2149   * @exception SQLException if a database-access error occurs
2150   */

2151  public void updateLong(int columnIndex, long x) throws SQLException JavaDoc
2152  {
2153    checkIfClosed();
2154
2155    if (inserting)
2156      insertStatement.setLong(columnIndex, x);
2157    else
2158    {
2159      checkUpdateFlagAndPrepareUpdateIfNeeded();
2160      updateStatement.setLong(columnIndex, x);
2161    }
2162
2163    tempRow[columnIndex - 1] = new Long JavaDoc(x);
2164  }
2165
2166  /**
2167   * JDBC 2.0 Update a column with a float value. The updateXXX() methods are
2168   * used to update column values in the current row, or the insert row. The
2169   * updateXXX() methods do not update the underlying database, instead the
2170   * updateRow() or insertRow() methods are called to update the database.
2171   *
2172   * @param columnIndex the first column is 1, the second is 2, ...
2173   * @param x the new column value
2174   * @exception SQLException if a database-access error occurs
2175   */

2176  public void updateFloat(int columnIndex, float x) throws SQLException JavaDoc
2177  {
2178    checkIfClosed();
2179
2180    if (inserting)
2181      insertStatement.setFloat(columnIndex, x);
2182    else
2183    {
2184      checkUpdateFlagAndPrepareUpdateIfNeeded();
2185      updateStatement.setFloat(columnIndex, x);
2186    }
2187
2188    tempRow[columnIndex - 1] = new Float JavaDoc(x);
2189  }
2190
2191  /**
2192   * JDBC 2.0 Update a column with a Double value. The updateXXX() methods are
2193   * used to update column values in the current row, or the insert row. The
2194   * updateXXX() methods do not update the underlying database, instead the
2195   * updateRow() or insertRow() methods are called to update the database.
2196   *
2197   * @param columnIndex the first column is 1, the second is 2, ...
2198   * @param x the new column value
2199   * @exception SQLException if a database-access error occurs
2200   */

2201  public void updateDouble(int columnIndex, double x) throws SQLException JavaDoc
2202  {
2203    checkIfClosed();
2204
2205    if (inserting)
2206      insertStatement.setDouble(columnIndex, x);
2207    else
2208    {
2209      checkUpdateFlagAndPrepareUpdateIfNeeded();
2210      updateStatement.setDouble(columnIndex, x);
2211    }
2212
2213    tempRow[columnIndex - 1] = new Double JavaDoc(x);
2214  }
2215
2216  /**
2217   * JDBC 2.0 Update a column with a BigDecimal value. The updateXXX() methods
2218   * are used to update column values in the current row, or the insert row. The
2219   * updateXXX() methods do not update the underlying database, instead the
2220   * updateRow() or insertRow() methods are called to update the database.
2221   *
2222   * @param columnIndex the first column is 1, the second is 2, ...
2223   * @param x the new column value
2224   * @exception SQLException if a database-access error occurs
2225   */

2226  public void updateBigDecimal(int columnIndex, BigDecimal JavaDoc x)
2227      throws SQLException JavaDoc
2228  {
2229    checkIfClosed();
2230
2231    if (inserting)
2232      insertStatement.setBigDecimal(columnIndex, x);
2233    else
2234    {
2235      checkUpdateFlagAndPrepareUpdateIfNeeded();
2236      updateStatement.setBigDecimal(columnIndex, x);
2237    }
2238
2239    tempRow[columnIndex - 1] = x;
2240  }
2241
2242  /**
2243   * JDBC 2.0 Update a column with a String value. The updateXXX() methods are
2244   * used to update column values in the current row, or the insert row. The
2245   * updateXXX() methods do not update the underlying database, instead the
2246   * updateRow() or insertRow() methods are called to update the database.
2247   *
2248   * @param columnIndex the first column is 1, the second is 2, ...
2249   * @param x the new column value
2250   * @exception SQLException if a database-access error occurs
2251   */

2252  public void updateString(int columnIndex, String JavaDoc x) throws SQLException JavaDoc
2253  {
2254    checkIfClosed();
2255
2256    if (inserting)
2257      insertStatement.setString(columnIndex, x);
2258    else
2259    {
2260      checkUpdateFlagAndPrepareUpdateIfNeeded();
2261      updateStatement.setString(columnIndex, x);
2262    }
2263
2264    tempRow[columnIndex - 1] = x;
2265  }
2266
2267  /**
2268   * JDBC 2.0 Update a column with a byte array value. The updateXXX() methods
2269   * are used to update column values in the current row, or the insert row. The
2270   * updateXXX() methods do not update the underlying database, instead the
2271   * updateRow() or insertRow() methods are called to update the database.
2272   *
2273   * @param columnIndex the first column is 1, the second is 2, ...
2274   * @param x the new column value
2275   * @exception SQLException if a database-access error occurs
2276   */

2277  public void updateBytes(int columnIndex, byte[] x) throws SQLException JavaDoc
2278  {
2279    checkIfClosed();
2280
2281    if (inserting)
2282      insertStatement.setBytes(columnIndex, x);
2283    else
2284    {
2285      checkUpdateFlagAndPrepareUpdateIfNeeded();
2286      updateStatement.setBytes(columnIndex, x);
2287    }
2288
2289    tempRow[columnIndex - 1] = x;
2290  }
2291
2292  /**
2293   * JDBC 2.0 Update a column with a Date value. The updateXXX() methods are
2294   * used to update column values in the current row, or the insert row. The
2295   * updateXXX() methods do not update the underlying database, instead the
2296   * updateRow() or insertRow() methods are called to update the database.
2297   *
2298   * @param columnIndex the first column is 1, the second is 2, ...
2299   * @param x the new column value
2300   * @exception SQLException if a database-access error occurs
2301   */

2302  public void updateDate(int columnIndex, java.sql.Date JavaDoc x) throws SQLException JavaDoc
2303  {
2304    checkIfClosed();
2305
2306    if (inserting)
2307      insertStatement.setDate(columnIndex, x);
2308    else
2309    {
2310      checkUpdateFlagAndPrepareUpdateIfNeeded();
2311      updateStatement.setDate(columnIndex, x);
2312    }
2313
2314    tempRow[columnIndex - 1] = x;
2315  }
2316
2317  /**
2318   * JDBC 2.0 Update a column with a Time value. The updateXXX() methods are
2319   * used to update column values in the current row, or the insert row. The
2320   * updateXXX() methods do not update the underlying database, instead the
2321   * updateRow() or insertRow() methods are called to update the database.
2322   *
2323   * @param columnIndex the first column is 1, the second is 2, ...
2324   * @param x the new column value
2325   * @exception SQLException if a database-access error occurs
2326   */

2327  public void updateTime(int columnIndex, java.sql.Time JavaDoc x) throws SQLException JavaDoc
2328  {
2329    checkIfClosed();
2330
2331    if (inserting)
2332      insertStatement.setTime(columnIndex, x);
2333    else
2334    {
2335      checkUpdateFlagAndPrepareUpdateIfNeeded();
2336      updateStatement.setTime(columnIndex, x);
2337    }
2338
2339    tempRow[columnIndex - 1] = x;
2340  }
2341
2342  /**
2343   * JDBC 2.0 Update a column with a Timestamp value. The updateXXX() methods
2344   * are used to update column values in the current row, or the insert row. The
2345   * updateXXX() methods do not update the underlying database, instead the
2346   * updateRow() or insertRow() methods are called to update the database.
2347   *
2348   * @param columnIndex the first column is 1, the second is 2, ...
2349   * @param x the new column value
2350   * @exception SQLException if a database-access error occurs
2351   */

2352  public void updateTimestamp(int columnIndex, java.sql.Timestamp JavaDoc x)
2353      throws SQLException JavaDoc
2354  {
2355    checkIfClosed();
2356
2357    if (inserting)
2358      insertStatement.setTimestamp(columnIndex, x);
2359    else
2360    {
2361      checkUpdateFlagAndPrepareUpdateIfNeeded();
2362      updateStatement.setTimestamp(columnIndex, x);
2363    }
2364
2365    tempRow[columnIndex - 1] = x;
2366  }
2367
2368  /**
2369   * JDBC 2.0 Update a column with an ascii stream value. The updateXXX()
2370   * methods are used to update column values in the current row, or the insert
2371   * row. The updateXXX() methods do not update the underlying database, instead
2372   * the updateRow() or insertRow() methods are called to update the database.
2373   *
2374   * @param columnIndex the first column is 1, the second is 2, ...
2375   * @param x the new column value
2376   * @param length the length of the stream
2377   * @exception SQLException if a database-access error occurs
2378   */

2379  public void updateAsciiStream(int columnIndex, java.io.InputStream JavaDoc x,
2380      int length) throws SQLException JavaDoc
2381  {
2382    this.updateBinaryStream(columnIndex, x, length);
2383  }
2384
2385  /**
2386   * JDBC 2.0 Update a column with a binary stream value. The updateXXX()
2387   * methods are used to update column values in the current row, or the insert
2388   * row. The updateXXX() methods do not update the underlying database, instead
2389   * the updateRow() or insertRow() methods are called to update the database.
2390   *
2391   * @param columnIndex the first column is 1, the second is 2, ...
2392   * @param x the new column value
2393   * @param length the length of the stream
2394   * @exception SQLException if a database-access error occurs
2395   */

2396  public void updateBinaryStream(int columnIndex, java.io.InputStream JavaDoc x,
2397      int length) throws SQLException JavaDoc
2398  {
2399    checkIfClosed();
2400
2401    byte[] content = new byte[length];
2402    try
2403    {
2404      x.read(content, 0, length);
2405    }
2406    catch (Exception JavaDoc ioe)
2407    {
2408      throw new SQLException JavaDoc("Problem with streaming of data");
2409    }
2410
2411    this.updateBytes(columnIndex, content);
2412  }
2413
2414  /**
2415   * JDBC 2.0 Update a column with a character stream value. The updateXXX()
2416   * methods are used to update column values in the current row, or the insert
2417   * row. The updateXXX() methods do not update the underlying database, instead
2418   * the updateRow() or insertRow() methods are called to update the database.
2419   *
2420   * @param columnIndex the first column is 1, the second is 2, ...
2421   * @param x the new column value
2422   * @param length the length of the stream
2423   * @exception SQLException if a database-access error occurs
2424   */

2425  public void updateCharacterStream(int columnIndex, java.io.Reader JavaDoc x,
2426      int length) throws SQLException JavaDoc
2427  {
2428    checkIfClosed();
2429
2430    char[] content = new char[length];
2431    try
2432    {
2433      x.read(content, 0, length);
2434    }
2435    catch (Exception JavaDoc ioe)
2436    {
2437      throw new SQLException JavaDoc("Problem with streaming of data");
2438    }
2439
2440    this.updateString(columnIndex, new String JavaDoc(content));
2441  }
2442
2443  /**
2444   * JDBC 2.0 Update a column with an Object value. The updateXXX() methods are
2445   * used to update column values in the current row, or the insert row. The
2446   * updateXXX() methods do not update the underlying database, instead the
2447   * updateRow() or insertRow() methods are called to update the database.
2448   *
2449   * @param columnIndex the first column is 1, the second is 2, ...
2450   * @param x the new column value
2451   * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
2452   * this is the number of digits after the decimal. For all other
2453   * types this value will be ignored.
2454   * @exception SQLException if a database-access error occurs
2455   */

2456  public void updateObject(int columnIndex, Object JavaDoc x, int scale)
2457      throws SQLException JavaDoc
2458  {
2459    checkIfClosed();
2460
2461    if (inserting)
2462      insertStatement.setObject(columnIndex, x, scale);
2463    else
2464    {
2465      checkUpdateFlagAndPrepareUpdateIfNeeded();
2466      updateStatement.setObject(columnIndex, x, scale);
2467    }
2468
2469    tempRow[columnIndex - 1] = x;
2470  }
2471
2472  /**
2473   * JDBC 2.0 Update a column with an Object value. The updateXXX() methods are
2474   * used to update column values in the current row, or the insert row. The
2475   * updateXXX() methods do not update the underlying database, instead the
2476   * updateRow() or insertRow() methods are called to update the database.
2477   *
2478   * @param columnIndex the first column is 1, the second is 2, ...
2479   * @param x the new column value
2480   * @exception SQLException if a database-access error occurs
2481   */

2482  public void updateObject(int columnIndex, Object JavaDoc x) throws SQLException JavaDoc
2483  {
2484    checkIfClosed();
2485
2486    if (inserting)
2487      insertStatement.setObject(columnIndex, x);
2488    else
2489    {
2490      checkUpdateFlagAndPrepareUpdateIfNeeded();
2491      updateStatement.setObject(columnIndex, x);
2492    }
2493
2494    tempRow[columnIndex - 1] = x;
2495  }
2496
2497  /**
2498   * JDBC 2.0 Update a column with a null value. The updateXXX() methods are
2499   * used to update column values in the current row, or the insert row. The
2500   * updateXXX() methods do not update the underlying database, instead the
2501   * updateRow() or insertRow() methods are called to update the database.
2502   *
2503   * @param columnName the name of the column
2504   * @exception SQLException if a database-access error occurs
2505   */

2506
2507  public void updateNull(String JavaDoc columnName) throws SQLException JavaDoc
2508  {
2509    this.updateNull(findColumn(columnName));
2510  }
2511
2512  /**
2513   * JDBC 2.0 Update a column with a boolean value. The updateXXX() methods are
2514   * used to update column values in the current row, or the insert row. The
2515   * updateXXX() methods do not update the underlying database, instead the
2516   * updateRow() or insertRow() methods are called to update the database.
2517   *
2518   * @param columnName the name of the column
2519   * @param x the new column value
2520   * @exception SQLException if a database-access error occurs
2521   */

2522  public void updateBoolean(String JavaDoc columnName, boolean x) throws SQLException JavaDoc
2523  {
2524    this.updateBoolean(findColumn(columnName), x);
2525  }
2526
2527  /**
2528   * JDBC 2.0 Update a column with a byte value. The updateXXX() methods are
2529   * used to update column values in the current row, or the insert row. The
2530   * updateXXX() methods do not update the underlying database, instead the
2531   * updateRow() or insertRow() methods are called to update the database.
2532   *
2533   * @param columnName the name of the column
2534   * @param x the new column value
2535   * @exception SQLException if a database-access error occurs
2536   */

2537  public void updateByte(String JavaDoc columnName, byte x) throws SQLException JavaDoc
2538  {
2539    this.updateByte(findColumn(columnName), x);
2540  }
2541
2542  /**
2543   * JDBC 2.0 Update a column with a short value. The updateXXX() methods are
2544   * used to update column values in the current row, or the insert row. The
2545   * updateXXX() methods do not update the underlying database, instead the
2546   * updateRow() or insertRow() methods are called to update the database.
2547   *
2548   * @param columnName the name of the column
2549   * @param x the new column value
2550   * @exception SQLException if a database-access error occurs
2551   */

2552  public void updateShort(String JavaDoc columnName, short x) throws SQLException JavaDoc
2553  {
2554    this.updateShort(findColumn(columnName), x);
2555  }
2556
2557  /**
2558   * JDBC 2.0 Update a column with an integer value. The updateXXX() methods are
2559   * used to update column values in the current row, or the insert row. The
2560   * updateXXX() methods do not update the underlying database, instead the
2561   * updateRow() or insertRow() methods are called to update the database.
2562   *
2563   * @param columnName the name of the column
2564   * @param x the new column value
2565   * @exception SQLException if a database-access error occurs
2566   */

2567  public void updateInt(String JavaDoc columnName, int x) throws SQLException JavaDoc
2568  {
2569    this.updateInt(findColumn(columnName), x);
2570  }
2571
2572  /**
2573   * JDBC 2.0 Update a column with a long value. The updateXXX() methods are
2574   * used to update column values in the current row, or the insert row. The
2575   * updateXXX() methods do not update the underlying database, instead the
2576   * updateRow() or insertRow() methods are called to update the database.
2577   *
2578   * @param columnName the name of the column
2579   * @param x the new column value
2580   * @exception SQLException if a database-access error occurs
2581   */

2582  public void updateLong(String JavaDoc columnName, long x) throws SQLException JavaDoc
2583  {
2584    this.updateLong(findColumn(columnName), x);
2585  }
2586
2587  /**
2588   * JDBC 2.0 Update a column with a float value. The updateXXX() methods are
2589   * used to update column values in the current row, or the insert row. The
2590   * updateXXX() methods do not update the underlying database, instead the
2591   * updateRow() or insertRow() methods are called to update the database.
2592   *
2593   * @param columnName the name of the column
2594   * @param x the new column value
2595   * @exception SQLException if a database-access error occurs
2596   */

2597  public void updateFloat(String JavaDoc columnName, float x) throws SQLException JavaDoc
2598  {
2599    this.updateFloat(findColumn(columnName), x);
2600  }
2601
2602  /**
2603   * JDBC 2.0 Update a column with a double value. The updateXXX() methods are
2604   * used to update column values in the current row, or the insert row. The
2605   * updateXXX() methods do not update the underlying database, instead the
2606   * updateRow() or insertRow() methods are called to update the database.
2607   *
2608   * @param columnName the name of the column
2609   * @param x the new column value
2610   * @exception SQLException if a database-access error occurs
2611   */

2612  public void updateDouble(String JavaDoc columnName, double x) throws SQLException JavaDoc
2613  {
2614    this.updateDouble(findColumn(columnName), x);
2615  }
2616
2617  /**
2618   * JDBC 2.0 Update a column with a BigDecimal value. The updateXXX() methods
2619   * are used to update column values in the current row, or the insert row. The
2620   * updateXXX() methods do not update the underlying database, instead the
2621   * updateRow() or insertRow() methods are called to update the database.
2622   *
2623   * @param columnName the name of the column
2624   * @param x the new column value
2625   * @exception SQLException if a database-access error occurs
2626   */

2627  public void updateBigDecimal(String JavaDoc columnName, BigDecimal JavaDoc x)
2628      throws SQLException JavaDoc
2629  {
2630    this.updateBigDecimal(findColumn(columnName), x);
2631  }
2632
2633  /**
2634   * JDBC 2.0 Update a column with a String value. The updateXXX() methods are
2635   * used to update column values in the current row, or the insert row. The
2636   * updateXXX() methods do not update the underlying database, instead the
2637   * updateRow() or insertRow() methods are called to update the database.
2638   *
2639   * @param columnName the name of the column
2640   * @param x the new column value
2641   * @exception SQLException if a database-access error occurs
2642   */

2643  public void updateString(String JavaDoc columnName, String JavaDoc x) throws SQLException JavaDoc
2644  {
2645    this.updateString(findColumn(columnName), x);
2646  }
2647
2648  /**
2649   * JDBC 2.0 Update a column with a byte array value. The updateXXX() methods
2650   * are used to update column values in the current row, or the insert row. The
2651   * updateXXX() methods do not update the underlying database, instead the
2652   * updateRow() or insertRow() methods are called to update the database.
2653   *
2654   * @param columnName the name of the column
2655   * @param x the new column value
2656   * @exception SQLException if a database-access error occurs
2657   */

2658  public void updateBytes(String JavaDoc columnName, byte[] x) throws SQLException JavaDoc
2659  {
2660    this.updateBytes(findColumn(columnName), x);
2661  }
2662
2663  /**
2664   * JDBC 2.0 Update a column with a Date value. The updateXXX() methods are
2665   * used to update column values in the current row, or the insert row. The
2666   * updateXXX() methods do not update the underlying database, instead the
2667   * updateRow() or insertRow() methods are called to update the database.
2668   *
2669   * @param columnName the name of the column
2670   * @param x the new column value
2671   * @exception SQLException if a database-access error occurs
2672   */

2673  public void updateDate(String JavaDoc columnName, java.sql.Date JavaDoc x)
2674      throws SQLException JavaDoc
2675  {
2676    this.updateDate(findColumn(columnName), x);
2677  }
2678
2679  /**
2680   * JDBC 2.0 Update a column with a Time value. The updateXXX() methods are
2681   * used to update column values in the current row, or the insert row. The
2682   * updateXXX() methods do not update the underlying database, instead the
2683   * updateRow() or insertRow() methods are called to update the database.
2684   *
2685   * @param columnName the name of the column
2686   * @param x the new column value
2687   * @exception SQLException if a database-access error occurs
2688   */

2689  public void updateTime(String JavaDoc columnName, java.sql.Time JavaDoc x)
2690      throws SQLException JavaDoc
2691  {
2692    this.updateTime(findColumn(columnName), x);
2693  }
2694
2695  /**
2696   * JDBC 2.0 Update a column with a Timestamp value. The updateXXX() methods
2697   * are used to update column values in the current row, or the insert row. The
2698   * updateXXX() methods do not update the underlying database, instead the
2699   * updateRow() or insertRow() methods are called to update the database.
2700   *
2701   * @param columnName the name of the column
2702   * @param x the new column value
2703   * @exception SQLException if a database-access error occurs
2704   */

2705  public void updateTimestamp(String JavaDoc columnName, java.sql.Timestamp JavaDoc x)
2706      throws SQLException JavaDoc
2707  {
2708    this.updateTimestamp(findColumn(columnName), x);
2709  }
2710
2711  /**
2712   * JDBC 2.0 Update a column with an ascii stream value. The updateXXX()
2713   * methods are used to update column values in the current row, or the insert
2714   * row. The updateXXX() methods do not update the underlying database, instead
2715   * the updateRow() or insertRow() methods are called to update the database.
2716   *
2717   * @param columnName the name of the column
2718   * @param x the new column value
2719   * @param length of the stream
2720   * @exception SQLException if a database-access error occurs
2721   */

2722  public void updateAsciiStream(String JavaDoc columnName, java.io.InputStream JavaDoc x,
2723      int length) throws SQLException JavaDoc
2724  {
2725    this.updateAsciiStream(findColumn(columnName), x, length);
2726  }
2727
2728  /**
2729   * JDBC 2.0 Update a column with a binary stream value. The updateXXX()
2730   * methods are used to update column values in the current row, or the insert
2731   * row. The updateXXX() methods do not update the underlying database, instead
2732   * the updateRow() or insertRow() methods are called to update the database.
2733   *
2734   * @param columnName the name of the column
2735   * @param x the new column value
2736   * @param length of the stream
2737   * @exception SQLException if a database-access error occurs
2738   */

2739  public void updateBinaryStream(String JavaDoc columnName, java.io.InputStream JavaDoc x,
2740      int length) throws SQLException JavaDoc
2741  {
2742    this.updateBinaryStream(findColumn(columnName), x, length);
2743  }
2744
2745  /**
2746   * JDBC 2.0 Update a column with a character stream value. The updateXXX()
2747   * methods are used to update column values in the current row, or the insert
2748   * row. The updateXXX() methods do not update the underlying database, instead
2749   * the updateRow() or insertRow() methods are called to update the database.
2750   *
2751   * @param columnName the name of the column
2752   * @param reader the stream
2753   * @param length of the stream
2754   * @exception SQLException if a database-access error occurs
2755   */

2756  public void updateCharacterStream(String JavaDoc columnName, java.io.Reader JavaDoc reader,
2757      int length) throws SQLException JavaDoc
2758  {
2759    this.updateCharacterStream(findColumn(columnName), reader, length);
2760  }
2761
2762  /**
2763   * JDBC 2.0 Update a column with an Object value. The updateXXX() methods are
2764   * used to update column values in the current row, or the insert row. The
2765   * updateXXX() methods do not update the underlying database, instead the
2766   * updateRow() or insertRow() methods are called to update the database.
2767   *
2768   * @param columnName the name of the column
2769   * @param x the new column value
2770   * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
2771   * this is the number of digits after the decimal. For all other
2772   * types this value will be ignored.
2773   * @exception SQLException if a database-access error occurs
2774   */

2775  public void updateObject(String JavaDoc columnName, Object JavaDoc x, int scale)
2776      throws SQLException JavaDoc
2777  {
2778    this.updateObject(findColumn(columnName), x, scale);
2779  }
2780
2781  /**
2782   * JDBC 2.0 Update a column with an Object value. The updateXXX() methods are
2783   * used to update column values in the current row, or the insert row. The
2784   * updateXXX() methods do not update the underlying database, instead the
2785   * updateRow() or insertRow() methods are called to update the database.
2786   *
2787   * @param columnName the name of the column
2788   * @param x the new column value
2789   * @exception SQLException if a database-access error occurs
2790   */

2791  public void updateObject(String JavaDoc columnName, Object JavaDoc x) throws SQLException JavaDoc
2792  {
2793    this.updateObject(findColumn(columnName), x);
2794  }
2795
2796  /**
2797   * JDBC 2.0 Insert the contents of the insert row into the result set and the
2798   * database. Must be on the insert row when this method is called.
2799   *
2800   * @exception SQLException if a database-access error occurs, if called when
2801   * not on the insert row, or if all non-nullable columns in the
2802   * insert row have not been given a value
2803   */

2804  public void insertRow() throws SQLException JavaDoc
2805  {
2806    checkIfClosed();
2807
2808    if (!inserting)
2809      throw new SQLException JavaDoc("insertRow cannot be called "
2810          + "when the cursor is not on the insert row");
2811
2812    // Insert row in underlying database
2813
try
2814    {
2815      insertStatement.executeUpdate();
2816    }
2817    finally
2818    {
2819      // Clean up
2820
insertStatement.clearParameters();
2821    }
2822
2823    // Insert row in this ResultSet
2824
if (data == null)
2825      data = new ArrayList JavaDoc();
2826    data.add(tempRow);
2827    nbOfRows++;
2828
2829    // Prepare for a new insert
2830
tempRow = new Object JavaDoc[nbOfColumns];
2831  }
2832
2833  /**
2834   * JDBC 2.0 Update the underlying database with the new contents of the
2835   * current row. Cannot be called when on the insert row.
2836   *
2837   * @exception SQLException if a database-access error occurs, or if called
2838   * when on the insert row
2839   */

2840  public void updateRow() throws SQLException JavaDoc
2841  {
2842    checkIfClosed();
2843
2844    if (inserting)
2845      throw new SQLException JavaDoc("updateRow cannot be called "
2846          + "when the cursor is on the insert row");
2847
2848    if (!updating)
2849      return;
2850
2851    // Add primary key info from current row
2852
for (int i = 0; i < primaryKeyColumns.length; ++i)
2853      updateStatement.setObject(nbOfColumns + i + 1, ((Object JavaDoc[]) data
2854          .get(currentRow))[findColumn(primaryKeyColumns[i]) - 1]);
2855
2856    // Update row in underlying database
2857
try
2858    {
2859      updateStatement.executeUpdate();
2860    }
2861    finally
2862    {
2863      // Clean up
2864
updateStatement.clearParameters();
2865    }
2866
2867    // Update row in this ResultSet
2868
data.set(currentRow, tempRow);
2869
2870    // Clean up
2871
tempRow = null;
2872    updating = false;
2873  }
2874
2875  /**
2876   * JDBC 2.0 Delete the current row from the result set and the underlying
2877   * database. Cannot be called when on the insert row.
2878   *
2879   * @exception SQLException if a database-access error occurs, or if called
2880   * when on the insert row.
2881   */

2882  public void deleteRow() throws SQLException JavaDoc
2883  {
2884    checkIfClosed();
2885
2886    if (inserting)
2887      throw new SQLException JavaDoc("deleteRow cannot be called "
2888          + "when the cursor is on the insert row");
2889
2890    this.checkRowPos();
2891
2892    if (deleteStatement == null)
2893      this.buildDeleteStatement();
2894
2895    // Add primary key info from current row
2896
for (int i = 0; i < primaryKeyColumns.length; ++i)
2897      deleteStatement
2898          .setObject(
2899              i + 1,
2900              ((Object JavaDoc[]) data.get(currentRow))[findColumn(primaryKeyColumns[i]) - 1]);
2901
2902    // Delete row from underlying database
2903
try
2904    {
2905      deleteStatement.executeUpdate();
2906    }
2907    finally
2908    {
2909      // Clean up
2910
deleteStatement.clearParameters();
2911    }
2912
2913    // Delete row from this ResultSet
2914
data.remove(currentRow);
2915    nbOfRows--;
2916
2917    // Deleting cancels all updates on the row
2918
if (updating)
2919      this.cancelRowUpdates();
2920  }
2921
2922  /**
2923   * JDBC 2.0 Refresh the value of the current row with its current value in the
2924   * database. Cannot be called when on the insert row. The refreshRow() method
2925   * provides a way for an application to explicitly tell the JDBC driver to
2926   * refetch a row(s) from the database. An application may want to call
2927   * refreshRow() when caching or prefetching is being done by the JDBC driver
2928   * to fetch the latest value of a row from the database. The JDBC driver may
2929   * actually refresh multiple rows at once if the fetch size is greater than
2930   * one. All values are refetched subject to the transaction isolation level
2931   * and cursor sensitivity. If refreshRow() is called after calling
2932   * updateXXX(), but before calling updateRow() then the updates made to the
2933   * row are lost. Calling refreshRow() frequently will likely slow performance.
2934   *
2935   * @exception SQLException if a database-access error occurs, or if called
2936   * when on the insert row.
2937   */

2938  public void refreshRow() throws SQLException JavaDoc
2939  {
2940    checkIfClosed();
2941
2942    if (inserting)
2943      throw new SQLException JavaDoc("refreshRow cannot be called "
2944          + "when the cursor is on the insert row");
2945
2946    this.checkRowPos();
2947
2948    if (refreshStatement == null)
2949      this.buildRefreshStatement();
2950
2951    // Add primary key info from current row
2952
for (int i = 0; i < primaryKeyColumns.length; ++i)
2953      refreshStatement
2954          .setObject(
2955              i + 1,
2956              ((Object JavaDoc[]) data.get(currentRow))[findColumn(primaryKeyColumns[i]) - 1]);
2957
2958    // Retrieve row from underlying database
2959
DriverResultSet res;
2960    try
2961    {
2962      res = (DriverResultSet) refreshStatement.executeQuery();
2963    }
2964    finally
2965    {
2966      // Clean up
2967
refreshStatement.clearParameters();
2968    }
2969
2970    // Refresh row in this ResultSet
2971
try
2972    {
2973      data.set(currentRow, res.data.get(0));
2974    }
2975    catch (NullPointerException JavaDoc e)
2976    {
2977      throw new SQLException JavaDoc("The current row has been "
2978          + "removed from the database");
2979    }
2980    finally
2981    {
2982      // Clean up
2983
res.close();
2984    }
2985
2986    // Refreshing cancels all updates on the row
2987
if (updating)
2988      this.cancelRowUpdates();
2989  }
2990
2991  /**
2992   * JDBC 2.0 The cancelRowUpdates() method may be called after calling an
2993   * updateXXX() method(s) and before calling updateRow() to rollback the
2994   * updates made to a row. If no updates have been made or updateRow() has
2995   * already been called, then this method has no effect.
2996   *
2997   * @exception SQLException if a database-access error occurs, or if called
2998   * when on the insert row.
2999   */

3000  public void cancelRowUpdates() throws SQLException JavaDoc
3001  {
3002    checkIfClosed();
3003
3004    if (inserting)
3005      throw new SQLException JavaDoc("cancelRowUpdates cannot be "
3006          + "called when the cursor is on the insert row");
3007
3008    if (!updating)
3009      return;
3010
3011    updateStatement.clearParameters();
3012    tempRow = null;
3013    updating = false;
3014  }
3015
3016  /**
3017   * JDBC 2.0 Move to the insert row. The current cursor position is remembered
3018   * while the cursor is positioned on the insert row. The insert row is a
3019   * special row associated with an updatable result set. It is essentially a
3020   * buffer where a new row may be constructed by calling the updateXXX()
3021   * methods prior to inserting the row into the result set. Only the
3022   * updateXXX(), getXXX(), and insertRow() methods may be called when the
3023   * cursor is on the insert row. All of the columns in a result set must be
3024   * given a value each time this method is called before calling insertRow().
3025   * UpdateXXX()must be called before getXXX() on a column.
3026   *
3027   * @exception SQLException if a database-access error occurs, or the result
3028   * set is not updatable
3029   */

3030  public void moveToInsertRow() throws SQLException JavaDoc
3031  {
3032    checkIfClosed();
3033
3034    if (inserting)
3035      return;
3036
3037    if (insertStatement == null)
3038      this.buildInsertStatement();
3039
3040    tempRow = new Object JavaDoc[nbOfColumns];
3041    inserting = true;
3042  }
3043
3044  /**
3045   * JDBC 2.0 Move the cursor to the remembered cursor position, usually the
3046   * current row. Has no effect unless the cursor is on the insert row.
3047   *
3048   * @exception SQLException if a database-access error occurs, or the result
3049   * set is not updatable
3050   */

3051  public void moveToCurrentRow() throws SQLException JavaDoc
3052  {
3053    checkIfClosed();
3054
3055    if (!inserting)
3056      return;
3057
3058    insertStatement.clearParameters();
3059    tempRow = null;
3060    inserting = false;
3061  }
3062
3063  //
3064
// ------------------------------------------
3065
// ResultSet meta-data related functions
3066
// ------------------------------------------
3067
//
3068

3069  /**
3070   * JDBC 2.0 Return the type of this result set. The type is determined based
3071   * on the statement that created the result set.
3072   *
3073   * @return TYPE_FORWARD_ONLY, TYPE_SCROLL_INSENSITIVE, or
3074   * TYPE_SCROLL_SENSITIVE
3075   * @exception SQLException if a database-access error occurs
3076   */

3077  public int getType() throws SQLException JavaDoc
3078  {
3079    return resultSetType;
3080  }
3081
3082  /**
3083   * JDBC 2.0 Return the concurrency of this result set. The concurrency used is
3084   * determined by the statement that created the result set.
3085   *
3086   * @return CONCUR_READ_ONLY or CONCUR_UPDATABLE
3087   * @exception SQLException if a database-access error occurs
3088   */

3089
3090  public int getConcurrency() throws SQLException JavaDoc
3091  {
3092    return resultSetConcurrency;
3093  }
3094
3095  /**
3096   * Closes the remote ResultSet if the ResultSet was streamed else just closes
3097   * the ResultSet locally.
3098   *
3099   * @exception SQLException if a database access error occurs
3100   */

3101  public void close() throws SQLException JavaDoc
3102  {
3103    if (isClosed)
3104      return;
3105
3106    closeCurrentStreamIfExists();
3107
3108    if (hasMoreData)
3109      this.connection.closeRemoteResultSet(cursorName);
3110    isClosed = true;
3111    // garbage collect some data
3112
this.data = null;
3113    this.fields = null;
3114    this.owningStatement = null;
3115    this.warnings = null;
3116  }
3117
3118  /**
3119   * A column may have the value of SQL NULL; wasNull() reports whether the last
3120   * column read had this special value. Note that you must first call getXXX on
3121   * a column to try to read its value and then call wasNull() to find if the
3122   * value was SQL NULL
3123   *
3124   * @return <code>true</code> if the last column read was SQL NULL
3125   * @exception SQLException if a database access error occurred
3126   */

3127
3128  public boolean wasNull() throws SQLException JavaDoc
3129  {
3130    return wasNullFlag;
3131  }
3132
3133  /**
3134   * JDBC 2.0 Return the <code>Statement</code> that produced the
3135   * <code>ResultSet</code>.
3136   *
3137   * @return the <code>Statement</code> that produced the
3138   * <code>ResultSet</code>, or null if the result was produced some
3139   * other way.
3140   * @exception SQLException if a database-access error occurs
3141   */

3142  public java.sql.Statement JavaDoc getStatement() throws SQLException JavaDoc
3143  {
3144    return owningStatement;
3145  }
3146
3147  /**
3148   * Set the hasMoreData boolean (is there more data to fetch from the
3149   * controller). This function is used by the ResultSet streaming feature.
3150   *
3151   * @param hasMore new value for hasMoreData
3152   */

3153  public void setHasMoreData(boolean hasMore)
3154  {
3155    hasMoreData = hasMore;
3156  }
3157
3158  /**
3159   * The numbers, types and properties of a <code>ResultSet</code>'s columns
3160   * are provided by the <code>getMetaData</code> method
3161   *
3162   * @return a description of the <code>ResultSet</code>'s columns
3163   * @exception SQLException if a database access error occurs
3164   */

3165  public java.sql.ResultSetMetaData JavaDoc getMetaData() throws SQLException JavaDoc
3166  {
3167    return new ResultSetMetaData(this);
3168  }
3169
3170  /**
3171   * Map a <code>ResultSet</code> column name to a <code>ResultSet</code>
3172   * column index
3173   *
3174   * @param columnName the name of the column
3175   * @return the column index
3176   * @exception SQLException if a database access error occurs
3177   */

3178  public int findColumn(String JavaDoc columnName) throws SQLException JavaDoc
3179  {
3180    if (columnName == null)
3181      throw new java.sql.SQLException JavaDoc("Invalid null column name");
3182
3183    checkIfClosed();
3184
3185    Integer JavaDoc index;
3186
3187    // Try to match the exact case (not per the spec!)
3188
if (sensitiveNameToIndex == null)
3189    {
3190      sensitiveNameToIndex = new Hashtable JavaDoc();
3191      buildIndexMapping(sensitiveNameToIndex, true);
3192    }
3193    index = (Integer JavaDoc) sensitiveNameToIndex.get(columnName);
3194    if (index != null)
3195      return index.intValue() + 1;
3196
3197    // Try to be case-insensitive (according to the spec)
3198
if (lowerNameToIndex == null)
3199    {
3200      lowerNameToIndex = new Hashtable JavaDoc();
3201      buildIndexMapping(lowerNameToIndex, false);
3202    }
3203    index = (Integer JavaDoc) lowerNameToIndex.get(columnName.toLowerCase());
3204    if (index != null)
3205      return index.intValue() + 1;
3206
3207    // nothing found
3208
throw new java.sql.SQLException JavaDoc("Column '" + columnName + "' not found.");
3209  }
3210
3211  // ****************************************************************
3212
//
3213
// END OF PUBLIC INTERFACE
3214
//
3215
// ****************************************************************
3216

3217  /**
3218   * Creates a new <code>DriverResultSet</code> object, deserializing it from
3219   * an input stream. MUST mirror the following serialization method
3220   * {@link org.continuent.sequoia.controller.backend.result.ControllerResultSet#sendToStream(org.continuent.sequoia.common.stream.DriverBufferedOutputStream)}
3221   *
3222   * @param conn the connection we read from and belong to
3223   * @throws IOException if a network problem occurs
3224   * @throws ProtocolException if a protocol error occurs
3225   */

3226
3227  public DriverResultSet(Connection conn) throws IOException JavaDoc, ProtocolException
3228  {
3229    this.connection = conn;
3230    DriverBufferedInputStream input = this.connection.socketInput;
3231    // Get the warning chain
3232
if (input.readBoolean())
3233    {
3234      warnings = new BackendDriverException(input);
3235    }
3236    else
3237      warnings = null;
3238    // Get the ResultSet metadata, deserialize columns information
3239
this.nbOfColumns = input.readInt();
3240    this.fields = new Field[nbOfColumns];
3241    for (int f = 0; f < this.nbOfColumns; f++)
3242      this.fields[f] = new Field(input);
3243
3244    if (!TypeTag.COL_TYPES.equals(new TypeTag(input)))
3245      throw new ProtocolException("Column types were expected");
3246
3247    // This could be just a boolean, see next line. But there is no real need
3248
// for change.
3249
this.nbOfRows = input.readInt();
3250
3251    // Receive java types
3252
if (this.nbOfRows > 0)
3253    {
3254      this.serializers = new SQLDataSerialization.Serializer[nbOfColumns];
3255      for (int col = 0; col < this.nbOfColumns; col++)
3256      {
3257        TypeTag tag = new TypeTag(input);
3258        try
3259        {
3260          serializers[col] = SQLDataSerialization.getSerializer(tag);
3261        }
3262        catch (IllegalArgumentException JavaDoc iae)
3263        {
3264          ProtocolException pe = new ProtocolException(
3265              "Protocol corruption: received unknown TypeTag " + tag
3266                  + " for column " + col);
3267          pe.initCause(iae);
3268          throw pe;
3269        }
3270      }
3271    }
3272
3273    receiveRows();
3274
3275    if (this.hasMoreData)
3276      this.cursorName = input.readLongUTF();
3277
3278    this.isClosed = false;
3279
3280  }
3281
3282  /**
3283   * Creates a new empty <code>DriverResultSet</code> object
3284   *
3285   * @param empty MUST be true
3286   */

3287  DriverResultSet(Connection conn, boolean empty)
3288  {
3289    if (!empty)
3290      throw new IllegalArgumentException JavaDoc(
3291          "empty flag must be true in DriverResultSet constructor");
3292
3293    connection = conn;
3294    inserting = false;
3295    updating = false;
3296    nbOfRows = 0;
3297    nbOfColumns = 0;
3298    hasMoreData = false;
3299    isClosed = false;
3300  }
3301
3302  /**
3303   * Creates a new <code>DriverResultSet</code> object with given data
3304   * (currently only supports one column, because it is used only to support
3305   * generated keys on batch update, when alwaysGetGeneratedKeys is set to true)
3306   *
3307   * @param conn
3308   * @param fromData List of objects to be inserted in this resultset
3309   * @param fromField Metadata for this colum
3310   */

3311  public DriverResultSet(Connection conn, ArrayList JavaDoc fromData, Field fromField)
3312  {
3313    this(conn, true);
3314    if (fromData != null && fromData.size() > 0)
3315    {
3316      nbOfRows = fromData.size();
3317      nbOfColumns = 1;
3318      hasMoreData = false;
3319      this.data = new ArrayList JavaDoc(this.nbOfRows);
3320      for (int i = 0; i < nbOfRows; i++)
3321      {
3322        Object JavaDoc[] row = new Object JavaDoc[nbOfColumns];
3323        row[0] = fromData.get(i);
3324        this.data.add(row);
3325      }
3326      this.fields = new Field[1];
3327      this.fields[0] = fromField;
3328    }
3329  }
3330
3331  /**
3332   * De-serialize only data rows, not any metadata. Useful for streaming. This
3333   * method MUST mirror the following serialization method:
3334   * {@link org.continuent.sequoia.controller.backend.result.ControllerResultSet#sendRowsToStream(org.continuent.sequoia.common.stream.DriverBufferedOutputStream)}
3335   *
3336   * @throws IOException stream error
3337   * @throws ProtocolException protocol corruption
3338   */

3339  private void receiveRows() throws IOException JavaDoc, ProtocolException
3340  {
3341
3342    DriverBufferedInputStream input = connection.socketInput;
3343    this.nbOfRows = input.readInt();
3344
3345    boolean[] nulls = new boolean[this.nbOfColumns];
3346
3347    // Receive the actual data
3348
this.data = new ArrayList JavaDoc(this.nbOfRows);
3349
3350    for (int r = 0; r < this.nbOfRows; r++)
3351    {
3352      if (!TypeTag.ROW.equals(new TypeTag(input)))
3353        throw new ProtocolException("A row was expected");
3354
3355      // First let's flag null values using a burst of booleans
3356
// TODO: we should compress this
3357
for (int col = 0; col < nbOfColumns; col++)
3358        nulls[col] = input.readBoolean();
3359
3360      Object JavaDoc[] row = new Object JavaDoc[this.nbOfColumns];
3361
3362      /**
3363       * Here we are sure that serializers are initialized because:
3364       * <p>
3365       * (1) we went through {@link #DriverResultSet(Connection)} at least once
3366       * before
3367       * <p>
3368       * (2) and there was a non-zero ResultSet transfered, else we would not
3369       * come here again.
3370       */

3371      for (int col = 0; col < this.nbOfColumns; col++)
3372        if (nulls[col])
3373          row[col] = null;
3374        else
3375          row[col] = serializers[col].receiveFromStream(input);
3376
3377      this.data.add(row);
3378    }
3379
3380    this.hasMoreData = input.readBoolean();
3381  }
3382
3383  /**
3384   * Set the statement.
3385   *
3386   * @param stmt The statement to set
3387   * @throws SQLException if an error occurs
3388   */

3389  protected void setStatement(Statement stmt) throws SQLException JavaDoc
3390  {
3391    owningStatement = stmt;
3392    fetchSize = stmt.getFetchSize();
3393    resultSetConcurrency = stmt.getResultSetConcurrency();
3394    resultSetType = stmt.getResultSetType();
3395  }
3396
3397  /**
3398   * Builds a hash between column names and their indices for fast retrieval. An
3399   * earlier name or label currently preempts any later name or label. This
3400   * looks compliant with the 3.0 spec and 4.0 draft.
3401   */

3402  private void buildIndexMapping(Hashtable JavaDoc table, boolean sensitive)
3403  {
3404    int numFields = nbOfColumns;
3405
3406    for (int i = 0; i < numFields; i++)
3407    {
3408      // pgjdbc and MySQL connector/J < 5 make no difference between name and
3409
// label. See SEQUOIA-746 and SEQUOIA-218
3410
putFieldNameInIndexMapping(fields[i].getFieldLabel(), i, sensitive, table);
3411      putFieldNameInIndexMapping(fields[i].getFieldName(), i, sensitive, table);
3412
3413      /*
3414       * Add the fully qualified name in any case. It is fully qualified and
3415       * guaranteed, therefore, not to be a duplicate unless it really is the
3416       * same column in the same table ...
3417       */

3418      putFieldNameInIndexMapping(fields[i].getFullName(), i, sensitive, table);
3419    }
3420  }
3421
3422  private void putFieldNameInIndexMapping(String JavaDoc name, int i,
3423      boolean sensitive, Hashtable JavaDoc table)
3424  {
3425    if ((name == null) || "".equals(name))
3426      return;
3427
3428    Integer JavaDoc index = new Integer JavaDoc(i);
3429
3430    String JavaDoc key = sensitive ? name : name.toLowerCase();
3431
3432    if (!table.containsKey(key))
3433      table.put(key, index);
3434  }
3435
3436  /**
3437   * Builds a delete statement for deleting rows with Updatable ResultSets
3438   *
3439   * @throws SQLException
3440   */

3441  private void buildDeleteStatement() throws SQLException JavaDoc
3442  {
3443    // Check that ResultSet can be updated
3444
this.checkUpdatability();
3445
3446    // Build delete statement for this ResultSet
3447
StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
3448    sb.append("DELETE FROM ");
3449    sb.append(fields[0].getTableName());
3450    sb.append(" WHERE ");
3451    for (int i = 0; i < primaryKeyColumns.length; ++i)
3452    {
3453      if (i > 0)
3454        sb.append(" AND ");
3455      sb.append(primaryKeyColumns[i]);
3456      sb.append(" = ?");
3457    }
3458
3459    // set delete statement
3460
deleteStatement = this.connection.prepareStatement(sb.toString());
3461  }
3462
3463  /**
3464   * Builds a insert statement for inserting rows with Updatable ResultSets
3465   *
3466   * @throws SQLException
3467   */

3468  private void buildInsertStatement() throws SQLException JavaDoc
3469  {
3470    // Check that ResultSet can be updated
3471
this.checkUpdatability();
3472
3473    // Build insert statement for this ResultSet
3474
StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
3475    sb.append("INSERT INTO ");
3476    sb.append(fields[0].getTableName());
3477    sb.append(" (");
3478    for (int i = 0; i < fields.length; ++i)
3479    {
3480      if (i > 0)
3481        sb.append(", ");
3482      sb.append(fields[i].getFieldName());
3483    }
3484    sb.append(") VALUES (");
3485    for (int i = 0; i < fields.length; ++i)
3486    {
3487      if (i > 0)
3488        sb.append(", ");
3489      sb.append("?");
3490    }
3491    sb.append(")");
3492
3493    // set insert statement
3494
insertStatement = this.connection.prepareStatement(sb.toString());
3495  }
3496
3497  /**
3498   * Builds a select statement for refreshing rows in Updatable ResultSets
3499   *
3500   * @throws SQLException
3501   */

3502  private void buildRefreshStatement() throws SQLException JavaDoc
3503  {
3504    // Check that ResultSet can be updated
3505
this.checkUpdatability();
3506
3507    // Build refresh statement for this ResultSet
3508
StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
3509    sb.append("SELECT ");
3510    for (int i = 0; i < fields.length; ++i)
3511    {
3512      if (i > 0)
3513        sb.append(", ");
3514      sb.append(fields[i].getFieldName());
3515    }
3516    sb.append(" FROM ");
3517    sb.append(fields[0].getTableName());
3518    sb.append(" WHERE ");
3519    for (int i = 0; i < primaryKeyColumns.length; ++i)
3520    {
3521      if (i > 0)
3522        sb.append(" AND ");
3523      sb.append(primaryKeyColumns[i]);
3524      sb.append(" = ?");
3525    }
3526
3527    // set refresh statement
3528
refreshStatement = this.connection.prepareStatement(sb.toString());
3529  }
3530
3531  /**
3532   * Builds an update statement for updating rows with Updatable ResultSets
3533   *
3534   * @throws SQLException
3535   */

3536  private void buildUpdateStatement() throws SQLException JavaDoc
3537  {
3538    // Check that ResultSet can be updated
3539
this.checkUpdatability();
3540
3541    // Build update statement for this ResultSet
3542
StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
3543    sb.append("UPDATE ");
3544    sb.append(fields[0].getTableName());
3545    sb.append(" SET ");
3546    for (int i = 0; i < fields.length; ++i)
3547    {
3548      if (i > 0)
3549        sb.append(", ");
3550      sb.append(fields[i].getFieldName());
3551      sb.append(" = ?");
3552    }
3553    sb.append(" WHERE ");
3554    for (int i = 0; i < primaryKeyColumns.length; ++i)
3555    {
3556      if (i > 0)
3557        sb.append(" AND ");
3558      sb.append(primaryKeyColumns[i]);
3559      sb.append(" = ?");
3560    }
3561
3562    // set update statement
3563
updateStatement = this.connection.prepareStatement(sb.toString());
3564  }
3565
3566  /**
3567   * Retrieves the primary key for the table referenced by this ResultSet
3568   *
3569   * @throws SQLException
3570   */

3571  private void extractPrimaryKey() throws SQLException JavaDoc
3572  {
3573    // sanity check
3574
if (fields[0].getTableName() == null
3575        || fields[0].getTableName().length() == 0)
3576      throw new SQLException JavaDoc("Could not extractPrimaryKeys: empty tablename");
3577
3578    ResultSet JavaDoc res = this.connection.getPrimaryKeys(null, null, fields[0]
3579        .getTableName());
3580
3581    try
3582    {
3583      primaryKeyColumns = new String JavaDoc[((DriverResultSet) res).nbOfRows];
3584      while (res.next())
3585        primaryKeyColumns[res.getRow() - 1] = res.getString(4);
3586    }
3587    finally
3588    {
3589      // Clean up
3590
res.close();
3591    }
3592  }
3593
3594  /**
3595   * Basic checks for Updatable ResultSets
3596   *
3597   * @throws SQLException
3598   */

3599  private void checkUpdatability() throws SQLException JavaDoc
3600  {
3601    // Check ResultSet Concurrency type
3602
switch (resultSetConcurrency)
3603    {
3604      case ResultSet.CONCUR_READ_ONLY :
3605        throw new SQLException JavaDoc("Cannot update ResultSet with "
3606            + "concurrency mode CONCUR_READ_ONLY");
3607      case ResultSet.CONCUR_UPDATABLE :
3608        break;
3609      default :
3610        throw new SQLException JavaDoc("Invalid ResultSet concurrency mode: "
3611            + resultSetConcurrency);
3612    }
3613
3614    // Check that the query selects only one table
3615
String JavaDoc tableName = fields[0].getTableName();
3616    for (int i = 1; i < nbOfColumns; ++i)
3617      if (!tableName.equals(fields[i].getTableName()))
3618        throw new SQLException JavaDoc(UPDATEABLE_MESSAGE);
3619
3620    // Check if need to get primary keys
3621
if (primaryKeyColumns == null)
3622      this.extractPrimaryKey();
3623
3624    // Check that the query selects the full primary key
3625
for (int i = 0; i < primaryKeyColumns.length; ++i)
3626      try
3627      {
3628        findColumn(primaryKeyColumns[i]);
3629      }
3630      catch (SQLException JavaDoc e)
3631      {
3632        throw new SQLException JavaDoc(UPDATEABLE_MESSAGE);
3633      }
3634  }
3635
3636  /**
3637   * Sanity checks for result parsing
3638   *
3639   * @param columnIndex the column to check
3640   * @throws SQLException if an error occurs
3641   */

3642  private void checkRowAndColPosAndSetNullFlag(int columnIndex)
3643      throws SQLException JavaDoc
3644  {
3645    checkIfClosed();
3646
3647    closeCurrentStreamIfExists();
3648
3649    if (!inserting)
3650      checkRowPos();
3651
3652    if (fields == null)
3653      throw new java.sql.SQLException JavaDoc("Query generated no fields for ResultSet");
3654
3655    if (columnIndex < 1 || columnIndex > nbOfColumns)
3656      throw new java.sql.SQLException JavaDoc("Column Index out of range ( "
3657          + columnIndex + " > " + nbOfColumns + ").");
3658
3659    try
3660    {
3661      Object JavaDoc obj;
3662      if (inserting || updating)
3663        obj = tempRow[columnIndex - 1];
3664      else
3665        obj = ((Object JavaDoc[]) data.get(currentRow))[columnIndex - 1];
3666
3667      if (obj == null)
3668        wasNullFlag = true;
3669      else
3670        wasNullFlag = false;
3671    }
3672    catch (NullPointerException JavaDoc e)
3673    {
3674      wasNullFlag = true;
3675    }
3676  }
3677
3678  /**
3679   * Checks that the cursor is on row in the ResultSet
3680   *
3681   * @throws SQLException
3682   */

3683  private void checkRowPos() throws SQLException JavaDoc
3684  {
3685    if (currentRow < 0)
3686      throw new SQLException JavaDoc("Before start of result set");
3687
3688    if (currentRow == nbOfRows)
3689      throw new SQLException JavaDoc("After end of result set");
3690  }
3691
3692  /**
3693   * Checks that the update flag is set when updating a row. The first time an
3694   * update is done on a row this method will prepare the ResultSet for update
3695   *
3696   * @throws SQLException
3697   */

3698  private void checkUpdateFlagAndPrepareUpdateIfNeeded() throws SQLException JavaDoc
3699  {
3700    if (updating)
3701      return;
3702
3703    this.checkRowPos();
3704
3705    if (updateStatement == null)
3706      this.buildUpdateStatement();
3707
3708    tempRow = (Object JavaDoc[]) ((Object JavaDoc[]) data.get(currentRow)).clone();
3709
3710    for (int i = 0; i < nbOfColumns; ++i)
3711      updateStatement.setObject(i + 1, tempRow[i]);
3712
3713    updating = true;
3714  }
3715
3716  /**
3717   * Check if the ResultSet if closed and throws a SQLException if so.
3718   *
3719   * @throws SQLException if the ResultSet is closed
3720   */

3721  private void checkIfClosed() throws SQLException JavaDoc
3722  {
3723    if (isClosed)
3724      throw new SQLException JavaDoc("Trying to access a closed ResultSet");
3725  }
3726
3727  /**
3728   * Check if the ResultSet can be scrolled.
3729   *
3730   * @throws SQLException if the ResultSet is closed or if its type is
3731   * TYPE_FORWARD_ONLY.
3732   */

3733  private void checkIfScrollable() throws SQLException JavaDoc
3734  {
3735    checkIfClosed();
3736    if (resultSetType == ResultSet.TYPE_FORWARD_ONLY)
3737    {
3738      throw new SQLException JavaDoc(
3739          "Operation requires a scrollable ResultSet, but this ResultSet is FORWARD_ONLY");
3740    }
3741  }
3742
3743  /**
3744   * Close a previously created input stream if needed.
3745   */

3746  private void closeCurrentStreamIfExists()
3747  {
3748    if (currentStream != null)
3749    {
3750      try
3751      {
3752        // since we use only ByteArrayInputStreams for now, this is a no-op.
3753
currentStream.close();
3754      }
3755      catch (IOException JavaDoc ignore)
3756      {
3757      }
3758      finally
3759      {
3760        currentStream = null;
3761      }
3762    }
3763  }
3764
3765  // -------------------------- JDBC 3.0
3766
// ----------------------------------------
3767

3768  /**
3769   * Retrieves the value of the designated column in the current row of this
3770   * <code>ResultSet</code> object as a <code>java.net.URL</code> object in
3771   * the Java programming language.
3772   *
3773   * @param columnIndex the index of the column 1 is the first, 2 is the
3774   * second,...
3775   * @return the column value as a <code>java.net.URL</code> object; if the
3776   * value is SQL <code>NULL</code>, the value returned is
3777   * <code>null</code> in the Java programming language
3778   * @exception SQLException if a database access error occurs, or if a URL is
3779   * malformed
3780   * @since JDK 1.4
3781   */

3782  public java.net.URL JavaDoc getURL(int columnIndex) throws SQLException JavaDoc
3783  {
3784    checkRowAndColPosAndSetNullFlag(columnIndex);
3785
3786    if (wasNullFlag)
3787      return null;
3788
3789    if (inserting || updating)
3790      return (URL JavaDoc) tempRow[columnIndex - 1];
3791    else
3792      return (URL JavaDoc) (((Object JavaDoc[]) data.get(currentRow))[columnIndex - 1]);
3793  }
3794
3795  /**
3796   * Retrieves the value of the designated column in the current row of this
3797   * <code>ResultSet</code> object as a <code>java.net.URL</code> object in
3798   * the Java programming language.
3799   *
3800   * @param columnName the SQL name of the column
3801   * @return the column value as a <code>java.net.URL</code> object; if the
3802   * value is SQL <code>NULL</code>, the value returned is
3803   * <code>null</code> in the Java programming language
3804   * @exception SQLException if a database access error occurs or if a URL is
3805   * malformed
3806   * @since JDK 1.4
3807   */

3808  public java.net.URL JavaDoc getURL(String JavaDoc columnName) throws SQLException JavaDoc
3809  {
3810    return getURL(findColumn(columnName));
3811  }
3812
3813  /**
3814   * Updates the designated column with a <code>java.sql.Ref</code> value. The
3815   * updater methods are used to update column values in the current row or the
3816   * insert row. The updater methods do not update the underlying database;
3817   * instead the <code>updateRow</code> or <code>insertRow</code> methods
3818   * are called to update the database.
3819   *
3820   * @param columnIndex the first column is 1, the second is 2, ...
3821   * @param x the new column value
3822   * @exception SQLException if a database access error occurs
3823   * @since JDK 1.4
3824   */

3825  public void updateRef(int columnIndex, java.sql.Ref JavaDoc x) throws SQLException JavaDoc
3826  {
3827    throw new NotImplementedException("updateRef");
3828  }
3829
3830  /**
3831   * Updates the designated column with a <code>java.sql.Ref</code> value. The
3832   * updater methods are used to update column values in the current row or the
3833   * insert row. The updater methods do not update the underlying database;
3834   * instead the <code>updateRow</code> or <code>insertRow</code> methods
3835   * are called to update the database.
3836   *
3837   * @param columnName the name of the column
3838   * @param x the new column value
3839   * @exception SQLException if a database access error occurs
3840   * @since JDK 1.4
3841   */

3842  public void updateRef(String JavaDoc columnName, java.sql.Ref JavaDoc x) throws SQLException JavaDoc
3843  {
3844    updateRef(findColumn(columnName), x);
3845  }
3846
3847  /**
3848   * Updates the designated column with a <code>java.sql.Blob</code> value.
3849   * The updater methods are used to update column values in the current row or
3850   * the insert row. The updater methods do not update the underlying database;
3851   * instead the <code>updateRow</code> or <code>insertRow</code> methods
3852   * are called to update the database.
3853   *
3854   * @param columnIndex the first column is 1, the second is 2, ...
3855   * @param x the new column value
3856   * @exception SQLException if a database access error occurs
3857   * @since JDK 1.4
3858   */

3859  public void updateBlob(int columnIndex, java.sql.Blob JavaDoc x) throws SQLException JavaDoc
3860  {
3861    throw new NotImplementedException("updateBlob");
3862  }
3863
3864  /**
3865   * Updates the designated column with a <code>java.sql.Blob</code> value.
3866   * The updater methods are used to update column values in the current row or
3867   * the insert row. The updater methods do not update the underlying database;
3868   * instead the <code>updateRow</code> or <code>insertRow</code> methods
3869   * are called to update the database.
3870   *
3871   * @param columnName the name of the column
3872   * @param x the new column value
3873   * @exception SQLException if a database access error occurs
3874   * @since JDK 1.4
3875   */

3876  public void updateBlob(String JavaDoc columnName, java.sql.Blob JavaDoc x)
3877      throws SQLException JavaDoc
3878  {
3879    updateBlob(findColumn(columnName), x);
3880  }
3881
3882  /**
3883   * Updates the designated column with a <code>java.sql.Clob</code> value.
3884   * The updater methods are used to update column values in the current row or
3885   * the insert row. The updater methods do not update the underlying database;
3886   * instead the <code>updateRow</code> or <code>insertRow</code> methods
3887   * are called to update the database.
3888   *
3889   * @param columnIndex the first column is 1, the second is 2, ...
3890   * @param x the new column value
3891   * @exception SQLException if a database access error occurs
3892   * @since JDK 1.4
3893   */

3894  public void updateClob(int columnIndex, java.sql.Clob JavaDoc x) throws SQLException JavaDoc
3895  {
3896    throw new NotImplementedException("updateClob");
3897  }
3898
3899  /**
3900   * Updates the designated column with a <code>java.sql.Clob</code> value.
3901   * The updater methods are used to update column values in the current row or
3902   * the insert row. The updater methods do not update the underlying database;
3903   * instead the <code>updateRow</code> or <code>insertRow</code> methods
3904   * are called to update the database.
3905   *
3906   * @param columnName the name of the column
3907   * @param x the new column value
3908   * @exception SQLException if a database access error occurs
3909   * @since JDK 1.4
3910   */

3911  public void updateClob(String JavaDoc columnName, java.sql.Clob JavaDoc x)
3912      throws SQLException JavaDoc
3913  {
3914    updateClob(findColumn(columnName), x);
3915  }
3916
3917  /**
3918   * Updates the designated column with a <code>java.sql.Array</code> value.
3919   * The updater methods are used to update column values in the current row or
3920   * the insert row. The updater methods do not update the underlying database;
3921   * instead the <code>updateRow</code> or <code>insertRow</code> methods
3922   * are called to update the database.
3923   *
3924   * @param columnIndex the first column is 1, the second is 2, ...
3925   * @param x the new column value
3926   * @exception SQLException if a database access error occurs
3927   * @since JDK 1.4
3928   */

3929  public void updateArray(int columnIndex, java.sql.Array JavaDoc x)
3930      throws SQLException JavaDoc
3931  {
3932    throw new NotImplementedException("updateArray");
3933  }
3934
3935  /**
3936   * Updates the designated column with a <code>java.sql.Array</code> value.
3937   * The updater methods are used to update column values in the current row or
3938   * the insert row. The updater methods do not update the underlying database;
3939   * instead the <code>updateRow</code> or <code>insertRow</code> methods
3940   * are called to update the database.
3941   *
3942   * @param columnName the name of the column
3943   * @param x the new column value
3944   * @exception SQLException if a database access error occurs
3945   * @since JDK 1.4
3946   */

3947  public void updateArray(String JavaDoc columnName, java.sql.Array JavaDoc x)
3948      throws SQLException JavaDoc
3949  {
3950    updateArray(findColumn(columnName), x);
3951  }
3952
3953  /**
3954   * Get the value of a column in the current row as a Java byte.
3955   *
3956   * @param columnIndex the first column is 1, the second is 2,...
3957   * @return the column value; 0 if SQL NULL
3958   * @exception SQLException if a database access error occurs
3959   */

3960  public byte getByte(int columnIndex) throws SQLException JavaDoc
3961  {
3962    checkRowAndColPosAndSetNullFlag(columnIndex);
3963
3964    if (wasNullFlag)
3965      return 0;
3966
3967    Object JavaDoc obj;
3968    if (inserting || updating)
3969      obj = tempRow[columnIndex - 1];
3970    else
3971      obj = ((Object JavaDoc[]) data.get(currentRow))[columnIndex - 1];
3972
3973    if (obj instanceof Number JavaDoc)
3974    {
3975      return ((Number JavaDoc) obj).byteValue();
3976    }
3977
3978    // the object is not of type number we parse the string representation
3979
try
3980    {
3981      String JavaDoc string = obj.toString();
3982      string = string.trim();
3983      return Byte.parseByte(string);
3984    }
3985    catch (NumberFormatException JavaDoc e)
3986    {
3987      throw new SQLException JavaDoc("the value " + obj.toString()
3988          + " is not a valid byte");
3989    }
3990  }
3991
3992  /**
3993   * @see java.lang.Object#toString()
3994   */

3995  public String JavaDoc toString()
3996  {
3997    return nbOfRows + " rows - " + nbOfColumns + " columns - current row:"
3998        + currentRow + " - hasMoreData:" + hasMoreData + " - isClosed:"
3999        + isClosed;
4000  }
4001}
Popular Tags