KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mysql > jdbc > ResultSet


1 /*
2    Copyright (C) 2002 MySQL AB
3
4       This program is free software; you can redistribute it and/or modify
5       it under the terms of the GNU General Public License as published by
6       the Free Software Foundation; either version 2 of the License, or
7       (at your option) any later version.
8
9       This program is distributed in the hope that it will be useful,
10       but WITHOUT ANY WARRANTY; without even the implied warranty of
11       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12       GNU General Public License for more details.
13
14       You should have received a copy of the GNU General Public License
15       along with this program; if not, write to the Free Software
16       Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18  */

19 package com.mysql.jdbc;
20
21 import java.io.ByteArrayInputStream JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.io.InputStream JavaDoc;
24 import java.io.ObjectInputStream JavaDoc;
25 import java.io.StringReader JavaDoc;
26
27 import java.math.BigDecimal JavaDoc;
28
29 import java.net.MalformedURLException JavaDoc;
30 import java.net.URL JavaDoc;
31
32 import java.sql.Array JavaDoc;
33 import java.sql.Date JavaDoc;
34 import java.sql.Ref JavaDoc;
35 import java.sql.SQLException JavaDoc;
36 import java.sql.SQLWarning JavaDoc;
37 import java.sql.Time JavaDoc;
38 import java.sql.Timestamp JavaDoc;
39 import java.sql.Types JavaDoc;
40
41 import java.util.Calendar JavaDoc;
42 import java.util.GregorianCalendar JavaDoc;
43 import java.util.HashMap JavaDoc;
44 import java.util.Map JavaDoc;
45 import java.util.TimeZone JavaDoc;
46
47
48 /**
49  * A ResultSet provides access to a table of data generated by executing a
50  * Statement. The table rows are retrieved in sequence. Within a row its
51  * column values can be accessed in any order.
52  *
53  * <P>
54  * A ResultSet maintains a cursor pointing to its current row of data.
55  * Initially the cursor is positioned before the first row. The 'next' method
56  * moves the cursor to the next row.
57  * </p>
58  *
59  * <P>
60  * The getXXX methods retrieve column values for the current row. You can
61  * retrieve values either using the index number of the column, or by using
62  * the name of the column. In general using the column index will be more
63  * efficient. Columns are numbered from 1.
64  * </p>
65  *
66  * <P>
67  * For maximum portability, ResultSet columns within each row should be read in
68  * left-to-right order and each column should be read only once.
69  * </p>
70  *
71  * <P>
72  * For the getXXX methods, the JDBC driver attempts to convert the underlying
73  * data to the specified Java type and returns a suitable Java value. See the
74  * JDBC specification for allowable mappings from SQL types to Java types with
75  * the ResultSet getXXX methods.
76  * </p>
77  *
78  * <P>
79  * Column names used as input to getXXX methods are case insenstive. When
80  * performing a getXXX using a column name, if several columns have the same
81  * name, then the value of the first matching column will be returned. The
82  * column name option is designed to be used when column names are used in the
83  * SQL Query. For columns that are NOT explicitly named in the query, it is
84  * best to use column numbers. If column names were used there is no way for
85  * the programmer to guarentee that they actually refer to the intended
86  * columns.
87  * </p>
88  *
89  * <P>
90  * A ResultSet is automatically closed by the Statement that generated it when
91  * that Statement is closed, re-executed, or is used to retrieve the next
92  * result from a sequence of multiple results.
93  * </p>
94  *
95  * <P>
96  * The number, types and properties of a ResultSet's columns are provided by
97  * the ResultSetMetaData object returned by the getMetaData method.
98  * </p>
99  *
100  * @author Mark Matthews
101  * @version $Id: ResultSet.java,v 1.18.2.25 2004/02/06 00:55:37 mmatthew Exp $
102  *
103  * @see ResultSetMetaData
104  * @see java.sql.ResultSet
105  */

106 public class ResultSet implements java.sql.ResultSet JavaDoc {
107     /**
108      * This method ends up being staticly synchronized, so just store our own
109      * copy....
110      */

111     private TimeZone JavaDoc defaultTimeZone;
112
113     /** The Connection instance that created us */
114     protected com.mysql.jdbc.Connection connection; // The connection that created us
115

116     /** Map column names (and all of their permutations) to column indices */
117     protected Map JavaDoc columnNameToIndex = null;
118
119     /** Map of fully-specified column names to column indices */
120     protected Map JavaDoc fullColumnNameToIndex = null;
121
122     /** The actual rows */
123     protected RowData rowData; // The results
124

125     /** The warning chain */
126     protected java.sql.SQLWarning JavaDoc warningChain = null;
127
128     /** The statement that created us */
129     protected com.mysql.jdbc.Statement owningStatement;
130
131     /** The catalog that was in use when we were created */
132     protected String JavaDoc catalog = null;
133
134     /**
135      * Any info message from the server that was created while generating this
136      * result set (if 'info parsing' is enabled for the connection).
137      */

138     protected String JavaDoc serverInfo = null;
139
140     /** The fields for this result set */
141     protected Field[] fields; // The fields
142

143     /** Pointer to current row data */
144     protected byte[][] thisRow; // Values for current row
145

146     /** Are we in the middle of doing updates to the current row? */
147     protected boolean doingUpdates = false;
148
149     /** Has this result set been closed? */
150     protected boolean isClosed = false;
151
152     /** Are we on the insert row? */
153     protected boolean onInsertRow = false;
154
155     /**
156      * Do we actually contain rows, or just information about
157      * UPDATE/INSERT/DELETE?
158      */

159     protected boolean reallyResult = false;
160
161     /** Did the previous value retrieval find a NULL? */
162     protected boolean wasNullFlag = false;
163
164     /**
165      * First character of the query that created this result set...Used to
166      * determine whether or not to parse server info messages in certain
167      * circumstances.
168      */

169     protected char firstCharOfQuery;
170
171     /** The current row #, -1 == before start of result set */
172     protected int currentRow = -1; // Cursor to current row;
173

174     /** The direction to fetch rows (always FETCH_FORWARD) */
175     protected int fetchDirection = FETCH_FORWARD;
176
177     /** The number of rows to fetch in one go... */
178     protected int fetchSize = 0;
179
180     /** Are we read-only or updatable? */
181     protected int resultSetConcurrency = 0;
182
183     /** Are we scroll-sensitive/insensitive? */
184     protected int resultSetType = 0;
185
186     /** How many rows were affected by UPDATE/INSERT/DELETE? */
187     protected long updateCount;
188
189     // These are longs for
190
// recent versions of the MySQL server.
191
//
192
// They get reduced to ints via the JDBC API,
193
// but can be retrieved through a MySQLStatement
194
// in their entirety.
195
//
196

197     /** Value generated for AUTO_INCREMENT columns */
198     protected long updateId = -1;
199     private Calendar JavaDoc fastDateCal = null;
200     private boolean hasBuiltIndexMapping = false;
201     private boolean useStrictFloatingPoint = false;
202
203     /**
204      * Create a result set for an executeUpdate statement.
205      *
206      * @param updateCount the number of rows affected by the update
207      * @param updateID the autoincrement value (if any)
208      */

209     public ResultSet(long updateCount, long updateID) {
210         this.updateCount = updateCount;
211         this.updateId = updateID;
212         reallyResult = false;
213         fields = new Field[0];
214     }
215
216     /**
217      * Create a new ResultSet
218      *
219      * @param catalog the database in use when we were created
220      * @param fields an array of Field objects (basically, the ResultSet
221      * MetaData)
222      * @param tuples actual row data
223      * @param conn the Connection that created us.
224      *
225      * @throws SQLException if an error occurs
226      */

227     public ResultSet(String JavaDoc catalog, Field[] fields, RowData tuples,
228         com.mysql.jdbc.Connection conn) throws SQLException JavaDoc {
229         this(fields, tuples);
230         setConnection(conn);
231         this.catalog = catalog;
232         
233     }
234
235     /**
236      * Creates a new ResultSet object.
237      *
238      * @param fields DOCUMENT ME!
239      * @param tuples DOCUMENT ME!
240      *
241      * @throws SQLException DOCUMENT ME!
242      */

243     public ResultSet(Field[] fields, RowData tuples) throws SQLException JavaDoc {
244         //_currentRow = -1;
245
this.fields = fields;
246         this.rowData = tuples;
247         this.updateCount = (long) rowData.size();
248
249         if (Driver.DEBUG) {
250             System.out.println("Retrieved " + updateCount + " rows");
251         }
252
253         this.reallyResult = true;
254
255         // Check for no results
256
if (this.rowData.size() > 0) {
257             //_thisRow = _rows.next();
258
if (this.updateCount == 1) {
259                 if (this.thisRow == null) {
260                     //_currentRow = -1;
261
this.rowData.close(); // empty result set
262
this.updateCount = -1;
263                 }
264             }
265         } else {
266             this.thisRow = null;
267         }
268
269         this.rowData.setOwner(this);
270     }
271
272     /**
273      * JDBC 2.0
274      *
275      * <p>
276      * Determine if the cursor is after the last row in the result set.
277      * </p>
278      *
279      * @return true if after the last row, false otherwise. Returns false when
280      * the result set contains no rows.
281      *
282      * @exception SQLException if a database-access error occurs.
283      */

284     public boolean isAfterLast() throws SQLException JavaDoc {
285         if (Driver.TRACE) {
286             Object JavaDoc[] args = { };
287             Debug.methodCall(this, "isAfterLast", args);
288         }
289
290         boolean b = rowData.isAfterLast();
291
292         if (Driver.TRACE) {
293             Debug.returnValue(this, "isAfterLast", new Boolean JavaDoc(b));
294         }
295
296         return b;
297     }
298
299     /**
300      * JDBC 2.0 Get an array column.
301      *
302      * @param i the first column is 1, the second is 2, ...
303      *
304      * @return an object representing an SQL array
305      *
306      * @throws SQLException if a database error occurs
307      * @throws NotImplemented DOCUMENT ME!
308      */

309     public java.sql.Array JavaDoc getArray(int i) throws SQLException JavaDoc {
310         throw new NotImplemented();
311     }
312
313     /**
314      * JDBC 2.0 Get an array column.
315      *
316      * @param colName the column name
317      *
318      * @return an object representing an SQL array
319      *
320      * @throws SQLException if a database error occurs
321      * @throws NotImplemented DOCUMENT ME!
322      */

323     public java.sql.Array JavaDoc getArray(String JavaDoc colName) throws SQLException JavaDoc {
324         throw new NotImplemented();
325     }
326
327     /**
328      * A column value can be retrieved as a stream of ASCII characters and then
329      * read in chunks from the stream. This method is particulary suitable
330      * for retrieving large LONGVARCHAR values. The JDBC driver will do any
331      * necessary conversion from the database format into ASCII.
332      *
333      * <p>
334      * <B>Note:</B> All the data in the returned stream must be read prior to
335      * getting the value of any other column. The next call to a get method
336      * implicitly closes the stream. Also, a stream may return 0 for
337      * available() whether there is data available or not.
338      * </p>
339      *
340      * @param columnIndex the first column is 1, the second is 2, ...
341      *
342      * @return a Java InputStream that delivers the database column value as a
343      * stream of one byte ASCII characters. If the value is SQL NULL
344      * then the result is null
345      *
346      * @exception java.sql.SQLException if a database access error occurs
347      *
348      * @see getBinaryStream
349      */

350     public InputStream JavaDoc getAsciiStream(int columnIndex)
351         throws java.sql.SQLException JavaDoc {
352         checkRowPos();
353
354         return getBinaryStream(columnIndex);
355     }
356
357     /**
358      * DOCUMENT ME!
359      *
360      * @param columnName DOCUMENT ME!
361      *
362      * @return DOCUMENT ME!
363      *
364      * @throws java.sql.SQLException DOCUMENT ME!
365      */

366     public InputStream JavaDoc getAsciiStream(String JavaDoc columnName)
367         throws java.sql.SQLException JavaDoc {
368         return getAsciiStream(findColumn(columnName));
369     }
370
371     //---------------------------------------------------------------------
372
// Traversal/Positioning
373
//---------------------------------------------------------------------
374

375     /**
376      * JDBC 2.0
377      *
378      * <p>
379      * Determine if the cursor is before the first row in the result set.
380      * </p>
381      *
382      * @return true if before the first row, false otherwise. Returns false
383      * when the result set contains no rows.
384      *
385      * @exception SQLException if a database-access error occurs.
386      */

387     public boolean isBeforeFirst() throws SQLException JavaDoc {
388         if (Driver.TRACE) {
389             Object JavaDoc[] args = { };
390             Debug.methodCall(this, "isBeforeFirst", args);
391         }
392
393         boolean b = rowData.isBeforeFirst();
394
395         if (Driver.TRACE) {
396             Debug.returnValue(this, "isBeforeFirst", new Boolean JavaDoc(b));
397         }
398
399         return b;
400     }
401
402     /**
403      * Get the value of a column in the current row as a java.math.BigDecimal
404      * object
405      *
406      * @param columnIndex the first column is 1, the second is 2...
407      * @param scale the number of digits to the right of the decimal
408      *
409      * @return the column value; if the value is SQL NULL, null
410      *
411      * @exception java.sql.SQLException if a database access error occurs
412      */

413     public BigDecimal JavaDoc getBigDecimal(int columnIndex, int scale)
414         throws java.sql.SQLException JavaDoc {
415         String JavaDoc stringVal = getString(columnIndex);
416         BigDecimal JavaDoc val;
417
418         if (stringVal != null) {
419             if (stringVal.length() == 0) {
420                 val = new BigDecimal JavaDoc(0);
421
422                 return val.setScale(scale);
423             }
424
425             try {
426                 val = new BigDecimal JavaDoc(stringVal);
427             } catch (NumberFormatException JavaDoc ex) {
428                 throw new java.sql.SQLException JavaDoc("Bad format for BigDecimal '"
429                     + stringVal + "' in column " + columnIndex + "("
430                     + fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
431             }
432
433             try {
434                 return val.setScale(scale);
435             } catch (ArithmeticException JavaDoc ex) {
436                 throw new java.sql.SQLException JavaDoc("Bad format for BigDecimal '"
437                     + stringVal + "' in column " + columnIndex + "("
438                     + fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
439             }
440         }
441
442         return null;
443     }
444
445     /**
446      * DOCUMENT ME!
447      *
448      * @param columnName DOCUMENT ME!
449      * @param scale DOCUMENT ME!
450      *
451      * @return DOCUMENT ME!
452      *
453      * @throws java.sql.SQLException DOCUMENT ME!
454      */

455     public BigDecimal JavaDoc getBigDecimal(String JavaDoc columnName, int scale)
456         throws java.sql.SQLException JavaDoc {
457         return getBigDecimal(findColumn(columnName), scale);
458     }
459
460     /**
461      * JDBC 2.0 Get the value of a column in the current row as a
462      * java.math.BigDecimal object.
463      *
464      * @param columnIndex the first column is 1, the second is 2, ...
465      *
466      * @return the column value (full precision); if the value is SQL NULL, the
467      * result is null
468      *
469      * @exception SQLException if a database-access error occurs.
470      * @throws java.sql.SQLException DOCUMENT ME!
471      */

472     public BigDecimal JavaDoc getBigDecimal(int columnIndex) throws SQLException JavaDoc {
473         String JavaDoc stringVal = getString(columnIndex);
474         BigDecimal JavaDoc val;
475
476         if (stringVal != null) {
477             if (stringVal.length() == 0) {
478                 val = new BigDecimal JavaDoc(0);
479
480                 return val;
481             }
482
483             try {
484                 val = new BigDecimal JavaDoc(stringVal);
485
486                 return val;
487             } catch (NumberFormatException JavaDoc ex) {
488                 throw new java.sql.SQLException JavaDoc("Bad format for BigDecimal '"
489                     + stringVal + "' in column " + columnIndex + "("
490                     + fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
491             }
492         }
493
494         return null;
495     }
496
497     /**
498      * JDBC 2.0 Get the value of a column in the current row as a
499      * java.math.BigDecimal object.
500      *
501      * @param columnName the name of the column to retrieve the value from
502      *
503      * @return the BigDecimal value in the column
504      *
505      * @throws SQLException if an error occurs
506      */

507     public BigDecimal JavaDoc getBigDecimal(String JavaDoc columnName)
508         throws SQLException JavaDoc {
509         return getBigDecimal(findColumn(columnName));
510     }
511
512     /**
513      * A column value can also be retrieved as a binary strea. This method is
514      * suitable for retrieving LONGVARBINARY values.
515      *
516      * @param columnIndex the first column is 1, the second is 2...
517      *
518      * @return a Java InputStream that delivers the database column value as a
519      * stream of bytes. If the value is SQL NULL, then the result is
520      * null
521      *
522      * @exception java.sql.SQLException if a database access error occurs
523      *
524      * @see getAsciiStream
525      * @see getUnicodeStream
526      */

527     public InputStream JavaDoc getBinaryStream(int columnIndex)
528         throws java.sql.SQLException JavaDoc {
529         checkRowPos();
530
531         byte[] b = getBytes(columnIndex);
532
533         if (b != null) {
534             return new ByteArrayInputStream JavaDoc(b);
535         }
536
537         return null;
538     }
539
540     /**
541      * DOCUMENT ME!
542      *
543      * @param columnName DOCUMENT ME!
544      *
545      * @return DOCUMENT ME!
546      *
547      * @throws java.sql.SQLException DOCUMENT ME!
548      */

549     public InputStream JavaDoc getBinaryStream(String JavaDoc columnName)
550         throws java.sql.SQLException JavaDoc {
551         return getBinaryStream(findColumn(columnName));
552     }
553
554     /**
555      * JDBC 2.0 Get a BLOB column.
556      *
557      * @param columnIndex the first column is 1, the second is 2, ...
558      *
559      * @return an object representing a BLOB
560      *
561      * @throws SQLException if an error occurs.
562      * @throws java.sql.SQLException DOCUMENT ME!
563      */

564     public java.sql.Blob JavaDoc getBlob(int columnIndex) throws SQLException JavaDoc {
565         checkRowPos();
566
567         if ((columnIndex < 1) || (columnIndex > fields.length)) {
568             throw new java.sql.SQLException JavaDoc("Column Index out of range ( "
569                 + columnIndex + " > " + fields.length + ").", SQLError.SQL_STATE_INVALID_COLUMN_NUMBER);
570         }
571
572         try {
573             if (thisRow[columnIndex - 1] == null) {
574                 wasNullFlag = true;
575             } else {
576                 wasNullFlag = false;
577             }
578         } catch (NullPointerException JavaDoc ex) {
579             wasNullFlag = true;
580         }
581
582         if (wasNullFlag) {
583             return null;
584         }
585
586         return new Blob(thisRow[columnIndex - 1]);
587     }
588
589     /**
590      * JDBC 2.0 Get a BLOB column.
591      *
592      * @param colName the column name
593      *
594      * @return an object representing a BLOB
595      *
596      * @throws SQLException if an error occurs.
597      */

598     public java.sql.Blob JavaDoc getBlob(String JavaDoc colName) throws SQLException JavaDoc {
599         return getBlob(findColumn(colName));
600     }
601
602     /**
603      * Get the value of a column in the current row as a Java boolean
604      *
605      * @param columnIndex the first column is 1, the second is 2...
606      *
607      * @return the column value, false for SQL NULL
608      *
609      * @exception java.sql.SQLException if a database access error occurs
610      */

611     public boolean getBoolean(int columnIndex) throws java.sql.SQLException JavaDoc {
612         String JavaDoc stringVal = getString(columnIndex);
613
614         if ((stringVal != null) && (stringVal.length() > 0)) {
615             int c = Character.toLowerCase(stringVal.charAt(0));
616
617             return ((c == 't') || (c == 'y') || (c == '1')
618             || stringVal.equals("-1"));
619         }
620
621         return false;
622     }
623
624     /**
625      * DOCUMENT ME!
626      *
627      * @param columnName DOCUMENT ME!
628      *
629      * @return DOCUMENT ME!
630      *
631      * @throws java.sql.SQLException DOCUMENT ME!
632      */

633     public boolean getBoolean(String JavaDoc columnName) throws java.sql.SQLException JavaDoc {
634         return getBoolean(findColumn(columnName));
635     }
636
637     /**
638      * Get the value of a column in the current row as a Java byte.
639      *
640      * @param columnIndex the first column is 1, the second is 2,...
641      *
642      * @return the column value; 0 if SQL NULL
643      *
644      * @exception java.sql.SQLException if a database access error occurs
645      * @throws SQLException DOCUMENT ME!
646      */

647     public byte getByte(int columnIndex) throws java.sql.SQLException JavaDoc {
648         checkRowPos();
649
650         try {
651             if (thisRow[columnIndex - 1] == null) {
652                 wasNullFlag = true;
653             } else {
654                 wasNullFlag = false;
655             }
656         } catch (NullPointerException JavaDoc E) {
657             wasNullFlag = true;
658         }
659
660         if (wasNullFlag) {
661             return 0;
662         }
663
664         Field field = fields[columnIndex - 1];
665
666         switch (field.getMysqlType()) {
667         case MysqlDefs.FIELD_TYPE_DECIMAL:
668         case MysqlDefs.FIELD_TYPE_TINY:
669         case MysqlDefs.FIELD_TYPE_SHORT:
670         case MysqlDefs.FIELD_TYPE_LONG:
671         case MysqlDefs.FIELD_TYPE_FLOAT:
672         case MysqlDefs.FIELD_TYPE_DOUBLE:
673         case MysqlDefs.FIELD_TYPE_LONGLONG:
674         case MysqlDefs.FIELD_TYPE_INT24:
675
676             try {
677                 String JavaDoc stringVal = getString(columnIndex);
678                 int decimalIndex = stringVal.indexOf(".");
679
680                 // Strip off the decimals
681
if (decimalIndex != -1) {
682                     stringVal = stringVal.substring(0, decimalIndex);
683                 }
684
685                 return Byte.parseByte(stringVal);
686             } catch (NumberFormatException JavaDoc NFE) {
687                 throw new SQLException JavaDoc("Value '" + getString(columnIndex)
688                     + "' is out of range [-127,127]", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
689             }
690
691         default:
692
693             try {
694                 String JavaDoc stringVal = getString(columnIndex);
695
696                 int decimalIndex = stringVal.indexOf(".");
697
698                 // Strip off the decimals
699
if (decimalIndex != -1) {
700                     stringVal = stringVal.substring(0, decimalIndex);
701                 }
702
703                 return Byte.parseByte(stringVal);
704             } catch (NumberFormatException JavaDoc NFE) {
705                 throw new SQLException JavaDoc("Value '" + getString(columnIndex)
706                     + "' is out of range [-127,127]", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
707             }
708
709             // FIXME: JDBC-Compliance test is broken, wants to convert string->byte(num)
710
//return _thisRow[columnIndex - 1][0];
711
}
712     }
713
714     /**
715      * DOCUMENT ME!
716      *
717      * @param columnName DOCUMENT ME!
718      *
719      * @return DOCUMENT ME!
720      *
721      * @throws java.sql.SQLException DOCUMENT ME!
722      */

723     public byte getByte(String JavaDoc columnName) throws java.sql.SQLException JavaDoc {
724         return getByte(findColumn(columnName));
725     }
726
727     /**
728      * Get the value of a column in the current row as a Java byte array.
729      *
730      * <p>
731      * <b>Be warned</b> If the blob is huge, then you may run out of memory.
732      * </p>
733      *
734      * @param columnIndex the first column is 1, the second is 2, ...
735      *
736      * @return the column value; if the value is SQL NULL, the result is null
737      *
738      * @exception java.sql.SQLException if a database access error occurs
739      */

740     public byte[] getBytes(int columnIndex) throws java.sql.SQLException JavaDoc {
741         checkRowPos();
742
743         try {
744             if (thisRow[columnIndex - 1] == null) {
745                 wasNullFlag = true;
746             } else {
747                 wasNullFlag = false;
748             }
749         } catch (NullPointerException JavaDoc E) {
750             wasNullFlag = true;
751         } catch (ArrayIndexOutOfBoundsException JavaDoc aioobEx) {
752             throw new java.sql.SQLException JavaDoc("Column Index out of range ( "
753                 + columnIndex + " > " + fields.length + ").", SQLError.SQL_STATE_INVALID_COLUMN_NUMBER);
754         }
755
756         if (wasNullFlag) {
757             return null;
758         } else {
759             return thisRow[columnIndex - 1];
760         }
761     }
762
763     /**
764      * DOCUMENT ME!
765      *
766      * @param columnName DOCUMENT ME!
767      *
768      * @return DOCUMENT ME!
769      *
770      * @throws java.sql.SQLException DOCUMENT ME!
771      */

772     public byte[] getBytes(String JavaDoc columnName) throws java.sql.SQLException JavaDoc {
773         return getBytes(findColumn(columnName));
774     }
775
776     //--------------------------JDBC 2.0-----------------------------------
777
//---------------------------------------------------------------------
778
// Getter's and Setter's
779
//---------------------------------------------------------------------
780

781     /**
782      * JDBC 2.0
783      *
784      * <p>
785      * Get the value of a column in the current row as a java.io.Reader.
786      * </p>
787      *
788      * @param columnIndex the column to get the value from
789      *
790      * @return the value in the column as a java.io.Reader.
791      *
792      * @throws SQLException if an error occurs
793      */

794     public java.io.Reader JavaDoc getCharacterStream(int columnIndex)
795         throws SQLException JavaDoc {
796         String JavaDoc stringVal = getString(columnIndex);
797
798         if (stringVal != null) {
799             return new StringReader JavaDoc(stringVal);
800         } else {
801             return null;
802         }
803     }
804
805     /**
806      * JDBC 2.0
807      *
808      * <p>
809      * Get the value of a column in the current row as a java.io.Reader.
810      * </p>
811      *
812      * @param columnName the column name to retrieve the value from
813      *
814      * @return the value as a java.io.Reader
815      *
816      * @throws SQLException if an error occurs
817      */

818     public java.io.Reader JavaDoc getCharacterStream(String JavaDoc columnName)
819         throws SQLException JavaDoc {
820         return getCharacterStream(findColumn(columnName));
821     }
822
823     /**
824      * JDBC 2.0 Get a CLOB column.
825      *
826      * @param i the first column is 1, the second is 2, ...
827      *
828      * @return an object representing a CLOB
829      *
830      * @throws SQLException if an error occurs
831      */

832     public java.sql.Clob JavaDoc getClob(int i) throws SQLException JavaDoc {
833         return new com.mysql.jdbc.Clob(getString(i));
834     }
835
836     /**
837      * JDBC 2.0 Get a CLOB column.
838      *
839      * @param colName the column name
840      *
841      * @return an object representing a CLOB
842      *
843      * @throws SQLException if an error occurs
844      */

845     public java.sql.Clob JavaDoc getClob(String JavaDoc colName) throws SQLException JavaDoc {
846         return getClob(findColumn(colName));
847     }
848
849     /**
850      * JDBC 2.0 Return the concurrency of this result set. The concurrency
851      * used is determined by the statement that created the result set.
852      *
853      * @return the concurrency type, CONCUR_READ_ONLY, etc.
854      *
855      * @throws SQLException if a database-access error occurs
856      */

857     public int getConcurrency() throws SQLException JavaDoc {
858         return (CONCUR_READ_ONLY);
859     }
860
861     /**
862      * DOCUMENT ME!
863      *
864      * @param conn the connection that created this result set.
865      */

866     public void setConnection(com.mysql.jdbc.Connection conn) {
867         this.connection = conn;
868
869         if (this.connection != null) {
870             this.useStrictFloatingPoint = this.connection.useStrictFloatingPoint();
871             this.defaultTimeZone = this.connection.getDefaultTimeZone();
872         } else {
873             this.defaultTimeZone = TimeZone.getDefault();
874         }
875     }
876
877     /**
878      * Get the name of the SQL cursor used by this ResultSet
879      *
880      * <p>
881      * In SQL, a result table is retrieved though a cursor that is named. The
882      * current row of a result can be updated or deleted using a positioned
883      * update/delete statement that references the cursor name.
884      * </p>
885      *
886      * <p>
887      * JDBC supports this SQL feature by providing the name of the SQL cursor
888      * used by a ResultSet. The current row of a ResulSet is also the current
889      * row of this SQL cursor.
890      * </p>
891      *
892      * <p>
893      * <B>Note:</B> If positioned update is not supported, a
894      * java.sql.SQLException is thrown.
895      * </p>
896      *
897      * @return the ResultSet's SQL cursor name.
898      *
899      * @exception java.sql.SQLException if a database access error occurs
900      */

901     public String JavaDoc getCursorName() throws java.sql.SQLException JavaDoc {
902         throw new java.sql.SQLException JavaDoc("Positioned Update not supported.",
903             "S1C00");
904     }
905
906     /**
907      * Get the value of a column in the current row as a java.sql.Date object
908      *
909      * @param columnIndex the first column is 1, the second is 2...
910      *
911      * @return the column value; null if SQL NULL
912      *
913      * @exception java.sql.SQLException if a database access error occurs
914      */

915     public java.sql.Date JavaDoc getDate(int columnIndex) throws java.sql.SQLException JavaDoc {
916         return getDate(columnIndex, null);
917     }
918
919     /**
920      * DOCUMENT ME!
921      *
922      * @param columnName DOCUMENT ME!
923      *
924      * @return DOCUMENT ME!
925      *
926      * @throws java.sql.SQLException DOCUMENT ME!
927      */

928     public java.sql.Date JavaDoc getDate(String JavaDoc columnName)
929         throws java.sql.SQLException JavaDoc {
930         return getDate(findColumn(columnName));
931     }
932
933     /**
934      * JDBC 2.0 Get the value of a column in the current row as a java.sql.Date
935      * object. Use the calendar to construct an appropriate millisecond value
936      * for the Date, if the underlying database doesn't store timezone
937      * information.
938      *
939      * @param columnIndex the first column is 1, the second is 2, ...
940      * @param cal the calendar to use in constructing the date
941      *
942      * @return the column value; if the value is SQL NULL, the result is null
943      *
944      * @exception SQLException if a database-access error occurs.
945      * @throws java.sql.SQLException DOCUMENT ME!
946      */

947     public java.sql.Date JavaDoc getDate(int columnIndex, Calendar JavaDoc cal)
948         throws SQLException JavaDoc {
949         Integer JavaDoc year = null;
950         Integer JavaDoc month = null;
951         Integer JavaDoc day = null;
952         String JavaDoc stringVal = "";
953
954         try {
955             stringVal = getString(columnIndex);
956
957             if (stringVal == null) {
958                 return null;
959             } else {
960                 int length = stringVal.length();
961
962                 if ((length > 0) && (stringVal.charAt(0) == '0')
963                         && (stringVal.equals("0000-00-00")
964                         || stringVal.equals("0000-00-00 00:00:00")
965                         || stringVal.equals("00000000000000")
966                         || stringVal.equals("0"))) {
967                     wasNullFlag = true;
968
969                     return null;
970                 } else if (fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_TIMESTAMP) {
971                     // Convert from TIMESTAMP
972
switch (length) {
973                     case 14:
974                     case 8: {
975                         year = new Integer JavaDoc(stringVal.substring(0, 4));
976                         month = new Integer JavaDoc(stringVal.substring(4, 6));
977                         day = new Integer JavaDoc(stringVal.substring(6, 8));
978
979                         return fastDateCreate(cal, year.intValue() - 1900,
980                             month.intValue() - 1, day.intValue());
981                     }
982
983                     case 12:
984                     case 10:
985                     case 6: {
986                         year = new Integer JavaDoc(stringVal.substring(0, 2));
987
988                         if (year.intValue() <= 69) {
989                             year = new Integer JavaDoc(year.intValue() + 100);
990                         }
991
992                         month = new Integer JavaDoc(stringVal.substring(2, 4));
993                         day = new Integer JavaDoc(stringVal.substring(4, 6));
994
995                         return fastDateCreate(cal, year.intValue(),
996                             month.intValue() - 1, day.intValue());
997                     }
998
999                     case 4: {
1000                        year = new Integer JavaDoc(stringVal.substring(0, 4));
1001
1002                        if (year.intValue() <= 69) {
1003                            year = new Integer JavaDoc(year.intValue() + 100);
1004                        }
1005
1006                        month = new Integer JavaDoc(stringVal.substring(2, 4));
1007
1008                        return fastDateCreate(cal, year.intValue(),
1009                            month.intValue() - 1, 1);
1010                    }
1011
1012                    case 2: {
1013                        year = new Integer JavaDoc(stringVal.substring(0, 2));
1014
1015                        if (year.intValue() <= 69) {
1016                            year = new Integer JavaDoc(year.intValue() + 100);
1017                        }
1018
1019                        return fastDateCreate(cal, year.intValue(), 0, 1);
1020                    }
1021
1022                    default:
1023                        throw new SQLException JavaDoc("Bad format for Date '"
1024                            + stringVal + "' in column " + columnIndex + "("
1025                            + fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1026                    } /* endswitch */
1027                } else if (fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {
1028                    year = new Integer JavaDoc(stringVal.substring(0, 4));
1029
1030                    return fastDateCreate(cal, year.intValue() - 1900, 0, 1);
1031                } else {
1032                    if (length < 10) {
1033                        throw new SQLException JavaDoc("Bad format for Date '"
1034                            + stringVal + "' in column " + columnIndex + "("
1035                            + fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1036                    }
1037
1038                    year = new Integer JavaDoc(stringVal.substring(0, 4));
1039                    month = new Integer JavaDoc(stringVal.substring(5, 7));
1040                    day = new Integer JavaDoc(stringVal.substring(8, 10));
1041                }
1042
1043                return fastDateCreate(cal, year.intValue() - 1900,
1044                    month.intValue() - 1, day.intValue());
1045            }
1046        } catch (Exception JavaDoc e) {
1047            throw new java.sql.SQLException JavaDoc("Cannot convert value '"
1048                + stringVal + "' from column " + columnIndex + "(" + stringVal
1049                + " ) to DATE.", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1050        }
1051    }
1052
1053    /**
1054     * Get the value of a column in the current row as a java.sql.Date object.
1055     * Use the calendar to construct an appropriate millisecond value for the
1056     * Date, if the underlying database doesn't store timezone information.
1057     *
1058     * @param columnName is the SQL name of the column
1059     * @param cal the calendar to use in constructing the date
1060     *
1061     * @return the column value; if the value is SQL NULL, the result is null
1062     *
1063     * @exception SQLException if a database-access error occurs.
1064     */

1065    public java.sql.Date JavaDoc getDate(String JavaDoc columnName, Calendar JavaDoc cal)
1066        throws SQLException JavaDoc {
1067        return getDate(columnName);
1068    }
1069
1070    /**
1071     * Get the value of a column in the current row as a Java double.
1072     *
1073     * @param columnIndex the first column is 1, the second is 2,...
1074     *
1075     * @return the column value; 0 if SQL NULL
1076     *
1077     * @exception java.sql.SQLException if a database access error occurs
1078     */

1079    public double getDouble(int columnIndex) throws java.sql.SQLException JavaDoc {
1080        try {
1081            return getDoubleInternal(columnIndex);
1082        } catch (NumberFormatException JavaDoc E) {
1083            throw new java.sql.SQLException JavaDoc("Bad format for number '"
1084                + new String JavaDoc(thisRow[columnIndex - 1]) + "' in column "
1085                + columnIndex + "(" + fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1086        }
1087    }
1088
1089    /**
1090     * DOCUMENT ME!
1091     *
1092     * @param columnName DOCUMENT ME!
1093     *
1094     * @return DOCUMENT ME!
1095     *
1096     * @throws java.sql.SQLException DOCUMENT ME!
1097     */

1098    public double getDouble(String JavaDoc columnName) throws java.sql.SQLException JavaDoc {
1099        return getDouble(findColumn(columnName));
1100    }
1101
1102    /**
1103     * JDBC 2.0 Give a hint as to the direction in which the rows in this
1104     * result set will be processed. The initial value is determined by the
1105     * statement that produced the result set. The fetch direction may be
1106     * changed at any time.
1107     *
1108     * @param direction the direction to fetch rows in.
1109     *
1110     * @exception SQLException if a database-access error occurs, or the result
1111     * set type is TYPE_FORWARD_ONLY and direction is not
1112     * FETCH_FORWARD. MM.MySQL actually ignores this, because it
1113     * has the whole result set anyway, so the direction is
1114     * immaterial.
1115     */

1116    public void setFetchDirection(int direction) throws SQLException JavaDoc {
1117        if ((direction != FETCH_FORWARD) && (direction != FETCH_REVERSE)
1118                && (direction != FETCH_UNKNOWN)) {
1119            throw new SQLException JavaDoc("Illegal value for fetch direction", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1120        } else {
1121            fetchDirection = direction;
1122        }
1123    }
1124
1125    /**
1126     * JDBC 2.0 Returns the fetch direction for this result set.
1127     *
1128     * @return the fetch direction for this result set.
1129     *
1130     * @exception SQLException if a database-access error occurs
1131     */

1132    public int getFetchDirection() throws SQLException JavaDoc {
1133        return fetchDirection;
1134    }
1135
1136    /**
1137     * JDBC 2.0 Give the JDBC driver a hint as to the number of rows that
1138     * should be fetched from the database when more rows are needed for this
1139     * result set. If the fetch size specified is zero, then the JDBC driver
1140     * ignores the value, and is free to make its own best guess as to what
1141     * the fetch size should be. The default value is set by the statement
1142     * that creates the result set. The fetch size may be changed at any
1143     * time.
1144     *
1145     * @param rows the number of rows to fetch
1146     *
1147     * @exception SQLException if a database-access error occurs, or the
1148     * condition 0 &lt;= rows &lt;= this.getMaxRows() is not
1149     * satisfied. Currently ignored by this driver.
1150     */

1151    public void setFetchSize(int rows) throws SQLException JavaDoc {
1152        if (rows < 0) { /* || rows > getMaxRows()*/
1153            throw new SQLException JavaDoc("Value must be between 0 and getMaxRows()",
1154                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1155        }
1156
1157        fetchSize = rows;
1158    }
1159
1160    /**
1161     * JDBC 2.0 Return the fetch size for this result set.
1162     *
1163     * @return the fetch size for this result set.
1164     *
1165     * @exception SQLException if a database-access error occurs
1166     */

1167    public int getFetchSize() throws SQLException JavaDoc {
1168        return fetchSize;
1169    }
1170
1171    /**
1172     * JDBC 2.0
1173     *
1174     * <p>
1175     * Determine if the cursor is on the first row of the result set.
1176     * </p>
1177     *
1178     * @return true if on the first row, false otherwise.
1179     *
1180     * @exception SQLException if a database-access error occurs.
1181     */

1182    public boolean isFirst() throws SQLException JavaDoc {
1183        if (Driver.TRACE) {
1184            Object JavaDoc[] args = { };
1185            Debug.methodCall(this, "isFirst", args);
1186        }
1187
1188        boolean b = rowData.isFirst();
1189
1190        if (Driver.TRACE) {
1191            Debug.returnValue(this, "isFirst", new Boolean JavaDoc(b));
1192        }
1193
1194        return b;
1195    }
1196
1197    /**
1198     * Get the value of a column in the current row as a Java float.
1199     *
1200     * @param columnIndex the first column is 1, the second is 2,...
1201     *
1202     * @return the column value; 0 if SQL NULL
1203     *
1204     * @exception java.sql.SQLException if a database access error occurs
1205     * @throws SQLException DOCUMENT ME!
1206     */

1207    public float getFloat(int columnIndex) throws java.sql.SQLException JavaDoc {
1208        checkRowPos();
1209
1210        String JavaDoc val = null;
1211
1212        try {
1213            val = getString(columnIndex);
1214
1215            if ((val != null) && (val.length() != 0)) {
1216                float f = Float.parseFloat(val);
1217
1218                return f;
1219            } else {
1220                return 0;
1221            }
1222        } catch (NumberFormatException JavaDoc nfe) {
1223            try {
1224                // To do: warn on under/overflow?
1225
return (float) Double.parseDouble(val);
1226            } catch (NumberFormatException JavaDoc newNfe) {
1227                ; // ignore, it's not a number
1228
}
1229
1230            throw new SQLException JavaDoc("Invalid value for getFloat() - '" + val
1231                + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1232        }
1233    }
1234
1235    /**
1236     * DOCUMENT ME!
1237     *
1238     * @param columnName DOCUMENT ME!
1239     *
1240     * @return DOCUMENT ME!
1241     *
1242     * @throws java.sql.SQLException DOCUMENT ME!
1243     */

1244    public float getFloat(String JavaDoc columnName) throws java.sql.SQLException JavaDoc {
1245        return getFloat(findColumn(columnName));
1246    }
1247
1248    /**
1249     * Get the value of a column in the current row as a Java int.
1250     *
1251     * @param columnIndex the first column is 1, the second is 2,...
1252     *
1253     * @return the column value; 0 if SQL NULL
1254     *
1255     * @exception java.sql.SQLException if a database access error occurs
1256     * @throws SQLException DOCUMENT ME!
1257     */

1258    public int getInt(int columnIndex) throws java.sql.SQLException JavaDoc {
1259        String JavaDoc val = null;
1260
1261        try {
1262            val = getString(columnIndex);
1263
1264            if ((val != null) && (val.length() != 0)) {
1265                if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)
1266                        && (val.indexOf(".") == -1)) {
1267                    return Integer.parseInt(val);
1268                } else {
1269                    // Convert floating point
1270
return (int) (Double.parseDouble(val));
1271                }
1272            } else {
1273                return 0;
1274            }
1275        } catch (NumberFormatException JavaDoc nfe) {
1276            try {
1277                // To do: warn on under/overflow?
1278
return (int) Double.parseDouble(val);
1279            } catch (NumberFormatException JavaDoc newNfe) {
1280                ; // ignore, it's not a number
1281
}
1282
1283            throw new SQLException JavaDoc("Invalid value for getInt() - '" + val + "'",
1284                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1285        }
1286    }
1287
1288    /**
1289     * DOCUMENT ME!
1290     *
1291     * @param columnName DOCUMENT ME!
1292     *
1293     * @return DOCUMENT ME!
1294     *
1295     * @throws java.sql.SQLException DOCUMENT ME!
1296     */

1297    public int getInt(String JavaDoc columnName) throws java.sql.SQLException JavaDoc {
1298        return getInt(findColumn(columnName));
1299    }
1300
1301    /**
1302     * JDBC 2.0
1303     *
1304     * <p>
1305     * Determine if the cursor is on the last row of the result set. Note:
1306     * Calling isLast() may be expensive since the JDBC driver might need to
1307     * fetch ahead one row in order to determine whether the current row is
1308     * the last row in the result set.
1309     * </p>
1310     *
1311     * @return true if on the last row, false otherwise.
1312     *
1313     * @exception SQLException if a database-access error occurs.
1314     */

1315    public boolean isLast() throws SQLException JavaDoc {
1316        if (Driver.TRACE) {
1317            Object JavaDoc[] args = { };
1318            Debug.methodCall(this, "isLast", args);
1319        }
1320
1321        boolean b = rowData.isLast();
1322
1323        if (Driver.TRACE) {
1324            Debug.returnValue(this, "relative", new Boolean JavaDoc(b));
1325        }
1326
1327        return b;
1328    }
1329
1330    /**
1331     * Get the value of a column in the current row as a Java long.
1332     *
1333     * @param columnIndex the first column is 1, the second is 2,...
1334     *
1335     * @return the column value; 0 if SQL NULL
1336     *
1337     * @exception java.sql.SQLException if a database access error occurs
1338     * @throws SQLException DOCUMENT ME!
1339     */

1340    public long getLong(int columnIndex) throws java.sql.SQLException JavaDoc {
1341        checkRowPos();
1342
1343        String JavaDoc val = null;
1344
1345        try {
1346            val = getString(columnIndex);
1347
1348            if ((val != null) && (val.length() != 0)) {
1349                if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)) {
1350                    return Long.parseLong(val);
1351                } else {
1352                    // Convert floating point
1353
return Double.doubleToLongBits(Double.parseDouble(val));
1354                }
1355            } else {
1356                return 0;
1357            }
1358        } catch (NumberFormatException JavaDoc nfe) {
1359            try {
1360                // To do: warn on under/overflow?
1361
return (long) Double.parseDouble(val);
1362            } catch (NumberFormatException JavaDoc newNfe) {
1363                ; // ignore, it's not a number
1364
}
1365
1366            throw new SQLException JavaDoc("Invalid value for getLong() - '" + val
1367                + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1368        }
1369    }
1370
1371    /**
1372     * DOCUMENT ME!
1373     *
1374     * @param columnName DOCUMENT ME!
1375     *
1376     * @return DOCUMENT ME!
1377     *
1378     * @throws java.sql.SQLException DOCUMENT ME!
1379     */

1380    public long getLong(String JavaDoc columnName) throws java.sql.SQLException JavaDoc {
1381        return getLong(findColumn(columnName));
1382    }
1383
1384    /**
1385     * The numbers, types and properties of a ResultSet's columns are provided
1386     * by the getMetaData method
1387     *
1388     * @return a description of the ResultSet's columns
1389     *
1390     * @exception java.sql.SQLException if a database access error occurs
1391     */

1392    public java.sql.ResultSetMetaData JavaDoc getMetaData()
1393        throws java.sql.SQLException JavaDoc {
1394        return new com.mysql.jdbc.ResultSetMetaData(fields);
1395    }
1396
1397    /**
1398     * Get the value of a column in the current row as a Java object
1399     *
1400     * <p>
1401     * This method will return the value of the given column as a Java object.
1402     * The type of the Java object will be the default Java Object type
1403     * corresponding to the column's SQL type, following the mapping specified
1404     * in the JDBC specification.
1405     * </p>
1406     *
1407     * <p>
1408     * This method may also be used to read database specific abstract data
1409     * types.
1410     * </p>
1411     *
1412     * @param columnIndex the first column is 1, the second is 2...
1413     *
1414     * @return a Object holding the column value
1415     *
1416     * @exception java.sql.SQLException if a database access error occurs
1417     * @throws SQLException DOCUMENT ME!
1418     */

1419    public Object JavaDoc getObject(int columnIndex) throws java.sql.SQLException JavaDoc {
1420        checkRowPos();
1421
1422        if (Driver.TRACE) {
1423            Object JavaDoc[] args = { new Integer JavaDoc(columnIndex) };
1424            Debug.methodCall(this, "getObject", args);
1425        }
1426
1427        try {
1428            if (thisRow[columnIndex - 1] == null) {
1429                wasNullFlag = true;
1430
1431                return null;
1432            }
1433        } catch (ArrayIndexOutOfBoundsException JavaDoc aioobEx) {
1434            throw new java.sql.SQLException JavaDoc("Column Index out of range ( "
1435                + columnIndex + " > " + fields.length + ").", SQLError.SQL_STATE_INVALID_COLUMN_NUMBER);
1436        }
1437
1438        wasNullFlag = false;
1439
1440        Field field;
1441        field = fields[columnIndex - 1];
1442
1443        switch (field.getSQLType()) {
1444        case Types.BIT:
1445            return new Boolean JavaDoc(getBoolean(columnIndex));
1446
1447        case Types.TINYINT:
1448
1449            return new Integer JavaDoc(getInt(columnIndex));
1450           
1451        case Types.SMALLINT:
1452            
1453            return new Integer JavaDoc(getInt(columnIndex));
1454           
1455        case Types.INTEGER:
1456
1457            if (field.isUnsigned()) {
1458                return new Long JavaDoc(getLong(columnIndex));
1459            } else {
1460                return new Integer JavaDoc(getInt(columnIndex));
1461            }
1462
1463        case Types.BIGINT:
1464
1465            if (field.isUnsigned()) {
1466                return getBigDecimal(columnIndex);
1467            } else {
1468                return new Long JavaDoc(getLong(columnIndex));
1469            }
1470
1471        case Types.DECIMAL:
1472        case Types.NUMERIC:
1473
1474            String JavaDoc stringVal = getString(columnIndex);
1475            BigDecimal JavaDoc val;
1476
1477            if (stringVal != null) {
1478                if (stringVal.length() == 0) {
1479                    val = new BigDecimal JavaDoc(0);
1480
1481                    return val;
1482                }
1483
1484                try {
1485                    val = new BigDecimal JavaDoc(stringVal);
1486                } catch (NumberFormatException JavaDoc ex) {
1487                    throw new java.sql.SQLException JavaDoc(
1488                        "Bad format for BigDecimal '" + stringVal
1489                        + "' in column " + columnIndex + "("
1490                        + fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1491                }
1492
1493                return val;
1494            } else {
1495                return null;
1496            }
1497
1498        case Types.REAL:
1499            return new Float JavaDoc(getFloat(columnIndex));
1500
1501        case Types.FLOAT:
1502        case Types.DOUBLE:
1503            return new Double JavaDoc(getDouble(columnIndex));
1504
1505        case Types.CHAR:
1506        case Types.VARCHAR:
1507        case Types.LONGVARCHAR:
1508            return getString(columnIndex);
1509
1510        case Types.BINARY:
1511        case Types.VARBINARY:
1512        case Types.LONGVARBINARY:
1513
1514            if (!field.isBlob()) {
1515                return getString(columnIndex);
1516            } else if (!field.isBinary()) {
1517                return getString(columnIndex);
1518            } else {
1519                byte[] data = getBytes(columnIndex);
1520                Object JavaDoc obj = data;
1521
1522                if ((data != null) && (data.length >= 2)) {
1523                    if ((data[0] == -84) && (data[1] == -19)) {
1524                        // Serialized object?
1525
try {
1526                            ByteArrayInputStream JavaDoc bytesIn = new ByteArrayInputStream JavaDoc(data);
1527                            ObjectInputStream JavaDoc objIn = new ObjectInputStream JavaDoc(bytesIn);
1528                            obj = objIn.readObject();
1529                            objIn.close();
1530                            bytesIn.close();
1531                        } catch (ClassNotFoundException JavaDoc cnfe) {
1532                            throw new SQLException JavaDoc("Class not found: "
1533                                + cnfe.toString()
1534                                + " while reading serialized object");
1535                        } catch (IOException JavaDoc ex) {
1536                            obj = data; // not serialized?
1537
}
1538                    }
1539                }
1540
1541                return obj;
1542            }
1543
1544        case Types.DATE:
1545            return getDate(columnIndex);
1546
1547        case Types.TIME:
1548            return getTime(columnIndex);
1549
1550        case Types.TIMESTAMP:
1551            return getTimestamp(columnIndex);
1552
1553        default:
1554            return getString(columnIndex);
1555        }
1556    }
1557
1558    /**
1559     * Get the value of a column in the current row as a Java object
1560     *
1561     * <p>
1562     * This method will return the value of the given column as a Java object.
1563     * The type of the Java object will be the default Java Object type
1564     * corresponding to the column's SQL type, following the mapping specified
1565     * in the JDBC specification.
1566     * </p>
1567     *
1568     * <p>
1569     * This method may also be used to read database specific abstract data
1570     * types.
1571     * </p>
1572     *
1573     * @param columnName is the SQL name of the column
1574     *
1575     * @return a Object holding the column value
1576     *
1577     * @exception java.sql.SQLException if a database access error occurs
1578     */

1579    public Object JavaDoc getObject(String JavaDoc columnName) throws java.sql.SQLException JavaDoc {
1580        return getObject(findColumn(columnName));
1581    }
1582
1583    /**
1584     * JDBC 2.0 Returns the value of column i as a Java object. Use the map to
1585     * determine the class from which to construct data of SQL structured and
1586     * distinct types.
1587     *
1588     * @param i the first column is 1, the second is 2, ...
1589     * @param map the mapping from SQL type names to Java classes
1590     *
1591     * @return an object representing the SQL value
1592     *
1593     * @throws SQLException because this is not implemented
1594     */

1595    public Object JavaDoc getObject(int i, java.util.Map JavaDoc map) throws SQLException JavaDoc {
1596        return getObject(i);
1597    }
1598
1599    /**
1600     * JDBC 2.0 Returns the value of column i as a Java object. Use the map to
1601     * determine the class from which to construct data of SQL structured and
1602     * distinct types.
1603     *
1604     * @param colName the column name
1605     * @param map the mapping from SQL type names to Java classes
1606     *
1607     * @return an object representing the SQL value
1608     *
1609     * @throws SQLException as this is not implemented
1610     */

1611    public Object JavaDoc getObject(String JavaDoc colName, java.util.Map JavaDoc map)
1612        throws SQLException JavaDoc {
1613        return getObject(findColumn(colName), map);
1614    }
1615
1616    /**
1617     * JDBC 2.0 Get a REF(&lt;structured-type&gt;) column.
1618     *
1619     * @param i the first column is 1, the second is 2, ...
1620     *
1621     * @return an object representing data of an SQL REF type
1622     *
1623     * @throws SQLException as this is not implemented
1624     * @throws NotImplemented DOCUMENT ME!
1625     */

1626    public java.sql.Ref JavaDoc getRef(int i) throws SQLException JavaDoc {
1627        throw new NotImplemented();
1628    }
1629
1630    /**
1631     * JDBC 2.0 Get a REF(&lt;structured-type&gt;) column.
1632     *
1633     * @param colName the column name
1634     *
1635     * @return an object representing data of an SQL REF type
1636     *
1637     * @throws SQLException as this method is not implemented.
1638     * @throws NotImplemented DOCUMENT ME!
1639     */

1640    public java.sql.Ref JavaDoc getRef(String JavaDoc colName) throws SQLException JavaDoc {
1641        throw new NotImplemented();
1642    }
1643
1644    /**
1645     * JDBC 2.0
1646     *
1647     * <p>
1648     * Determine the current row number. The first row is number 1, the second
1649     * number 2, etc.
1650     * </p>
1651     *
1652     * @return the current row number, else return 0 if there is no current row
1653     *
1654     * @exception SQLException if a database-access error occurs.
1655     */

1656    public int getRow() throws SQLException JavaDoc {
1657        if (Driver.TRACE) {
1658            Object JavaDoc[] args = { };
1659            Debug.methodCall(this, "getRow", args);
1660        }
1661
1662        int currentRow = rowData.getCurrentRowNumber();
1663        int row = 0;
1664
1665        // Non-dynamic result sets can be interrogated
1666
// for this information
1667
if (!rowData.isDynamic()) {
1668            if ((currentRow < 0) || rowData.isAfterLast() || rowData.isEmpty()) {
1669                row = 0;
1670            } else {
1671                row = currentRow + 1;
1672            }
1673        } else {
1674            // dynamic (streaming) can not
1675
row = currentRow + 1;
1676        }
1677
1678        if (Driver.TRACE) {
1679            Debug.returnValue(this, "getRow", new Integer JavaDoc(row));
1680        }
1681
1682        if (Driver.TRACE) {
1683            Debug.returnValue(this, "getRow", new Integer JavaDoc(row));
1684        }
1685
1686        return row;
1687    }
1688
1689    /**
1690     * Get the value of a column in the current row as a Java short.
1691     *
1692     * @param columnIndex the first column is 1, the second is 2,...
1693     *
1694     * @return the column value; 0 if SQL NULL
1695     *
1696     * @exception java.sql.SQLException if a database access error occurs
1697     * @throws SQLException DOCUMENT ME!
1698     */

1699    public short getShort(int columnIndex) throws java.sql.SQLException JavaDoc {
1700        checkRowPos();
1701
1702        String JavaDoc val = null;
1703
1704        try {
1705            val = getString(columnIndex);
1706
1707            if ((val != null) && (val.length() != 0)) {
1708                if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)
1709                        && (val.indexOf(".") == -1)) {
1710                    return Short.parseShort(val);
1711                } else {
1712                    // Convert floating point
1713
return (short) (Double.parseDouble(val));
1714                }
1715            } else {
1716                return 0;
1717            }
1718        } catch (NumberFormatException JavaDoc nfe) {
1719            try {
1720                // To do: warn on under/overflow?
1721
return (short) Double.parseDouble(val);
1722            } catch (NumberFormatException JavaDoc newNfe) {
1723                ; // ignore, it's not a number
1724
}
1725
1726            throw new SQLException JavaDoc("Invalid value for getShort() - '" + val
1727                + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1728        }
1729    }
1730
1731    /**
1732     * DOCUMENT ME!
1733     *
1734     * @param columnName DOCUMENT ME!
1735     *
1736     * @return DOCUMENT ME!
1737     *
1738     * @throws java.sql.SQLException DOCUMENT ME!
1739     */

1740    public short getShort(String JavaDoc columnName) throws java.sql.SQLException JavaDoc {
1741        return getShort(findColumn(columnName));
1742    }
1743
1744    /**
1745     * JDBC 2.0 Return the Statement that produced the ResultSet.
1746     *
1747     * @return the Statment that produced the result set, or null if the result
1748     * was produced some other way.
1749     *
1750     * @exception SQLException if a database-access error occurs
1751     */

1752    public java.sql.Statement JavaDoc getStatement() throws SQLException JavaDoc {
1753        return (java.sql.Statement JavaDoc) owningStatement;
1754    }
1755
1756    /**
1757     * Get the value of a column in the current row as a Java String
1758     *
1759     * @param columnIndex the first column is 1, the second is 2...
1760     *
1761     * @return the column value, null for SQL NULL
1762     *
1763     * @exception java.sql.SQLException if a database access error occurs
1764     * @throws SQLException DOCUMENT ME!
1765     */

1766    public String JavaDoc getString(int columnIndex) throws java.sql.SQLException JavaDoc {
1767        checkRowPos();
1768
1769        if (fields == null) {
1770            throw new java.sql.SQLException JavaDoc("Query generated no fields for ResultSet",
1771                SQLError.SQL_STATE_INVALID_COLUMN_NUMBER);
1772        }
1773
1774        try {
1775            if (thisRow[columnIndex - 1] == null) {
1776                wasNullFlag = true;
1777
1778                return null;
1779            } else {
1780                wasNullFlag = false;
1781            }
1782        } catch (NullPointerException JavaDoc E) {
1783            wasNullFlag = true;
1784
1785            return null;
1786        } catch (ArrayIndexOutOfBoundsException JavaDoc aioobEx) {
1787            throw new java.sql.SQLException JavaDoc("Column Index out of range ( "
1788                + columnIndex + " > " + fields.length + ").", SQLError.SQL_STATE_INVALID_COLUMN_NUMBER);
1789        }
1790
1791        String JavaDoc stringVal = null;
1792        columnIndex--; // JDBC is 1-based, Java is not !?
1793

1794        if ((connection != null) && connection.useUnicode()) {
1795            try {
1796                String JavaDoc encoding = this.fields[columnIndex].getCharacterSet();
1797
1798                if (encoding == null) {
1799                    stringVal = new String JavaDoc(thisRow[columnIndex]);
1800                } else {
1801                    SingleByteCharsetConverter converter = this.connection.getCharsetConverter(encoding);
1802
1803                    if (converter != null) {
1804                        stringVal = converter.toString(thisRow[columnIndex]);
1805                    } else {
1806                        stringVal = new String JavaDoc(thisRow[columnIndex], encoding);
1807                    }
1808                }
1809            } catch (java.io.UnsupportedEncodingException JavaDoc E) {
1810                throw new SQLException JavaDoc("Unsupported character encoding '"
1811                    + connection.getEncoding() + "'.", SQLError.SQL_STATE_GENERAL_ERROR);
1812            }
1813        } else {
1814            stringVal = StringUtils.toAsciiString(thisRow[columnIndex]);
1815        }
1816
1817        return stringVal;
1818    }
1819
1820    /**
1821     * The following routines simply convert the columnName into a columnIndex
1822     * and then call the appropriate routine above.
1823     *
1824     * @param columnName is the SQL name of the column
1825     *
1826     * @return the column value
1827     *
1828     * @exception java.sql.SQLException if a database access error occurs
1829     */

1830    public String JavaDoc getString(String JavaDoc columnName) throws java.sql.SQLException JavaDoc {
1831        return getString(findColumn(columnName));
1832    }
1833
1834    /**
1835     * Get the value of a column in the current row as a java.sql.Time object
1836     *
1837     * @param columnIndex the first column is 1, the second is 2...
1838     *
1839     * @return the column value; null if SQL NULL
1840     *
1841     * @throws java.sql.SQLException if a database access error occurs
1842     */

1843    public synchronized Time JavaDoc getTime(int columnIndex) throws java.sql.SQLException JavaDoc {
1844        return getTimeInternal(columnIndex, this.defaultTimeZone);
1845    }
1846
1847    /**
1848     * Get the value of a column in the current row as a java.sql.Time object.
1849     *
1850     * @param columnName is the SQL name of the column
1851     *
1852     * @return the column value; if the value is SQL NULL, the result is null
1853     *
1854     * @throws java.sql.SQLException if a database-access error occurs.
1855     */

1856    public Time JavaDoc getTime(String JavaDoc columnName) throws java.sql.SQLException JavaDoc {
1857        return getTime(findColumn(columnName));
1858    }
1859
1860    /**
1861     * Get the value of a column in the current row as a java.sql.Time object.
1862     * Use the calendar to construct an appropriate millisecond value for the
1863     * Time, if the underlying database doesn't store timezone information.
1864     *
1865     * @param columnIndex the first column is 1, the second is 2, ...
1866     * @param cal the calendar to use in constructing the time
1867     *
1868     * @return the column value; if the value is SQL NULL, the result is null
1869     *
1870     * @exception SQLException if a database-access error occurs.
1871     */

1872    public java.sql.Time JavaDoc getTime(int columnIndex, Calendar JavaDoc cal)
1873        throws SQLException JavaDoc {
1874        return getTimeInternal(columnIndex, cal.getTimeZone());
1875    }
1876
1877    /**
1878     * Get the value of a column in the current row as a java.sql.Time object.
1879     * Use the calendar to construct an appropriate millisecond value for the
1880     * Time, if the underlying database doesn't store timezone information.
1881     *
1882     * @param columnName is the SQL name of the column
1883     * @param cal the calendar to use in constructing the time
1884     *
1885     * @return the column value; if the value is SQL NULL, the result is null
1886     *
1887     * @exception SQLException if a database-access error occurs.
1888     */

1889    public java.sql.Time JavaDoc getTime(String JavaDoc columnName, Calendar JavaDoc cal)
1890        throws SQLException JavaDoc {
1891        return getTime(findColumn(columnName), cal);
1892    }
1893
1894    /**
1895     * Get the value of a column in the current row as a java.sql.Timestamp
1896     * object
1897     *
1898     * @param columnIndex the first column is 1, the second is 2...
1899     *
1900     * @return the column value; null if SQL NULL
1901     *
1902     * @exception java.sql.SQLException if a database access error occurs
1903     */

1904    public synchronized Timestamp JavaDoc getTimestamp(int columnIndex) throws java.sql.SQLException JavaDoc {
1905        return getTimestampInternal(columnIndex, this.defaultTimeZone);
1906    }
1907
1908    /**
1909     * DOCUMENT ME!
1910     *
1911     * @param columnName DOCUMENT ME!
1912     *
1913     * @return DOCUMENT ME!
1914     *
1915     * @throws java.sql.SQLException DOCUMENT ME!
1916     */

1917    public Timestamp JavaDoc getTimestamp(String JavaDoc columnName)
1918        throws java.sql.SQLException JavaDoc {
1919        return getTimestamp(findColumn(columnName));
1920    }
1921
1922    /**
1923     * Get the value of a column in the current row as a java.sql.Timestamp
1924     * object. Use the calendar to construct an appropriate millisecond value
1925     * for the Timestamp, if the underlying database doesn't store timezone
1926     * information.
1927     *
1928     * @param columnIndex the first column is 1, the second is 2, ...
1929     * @param cal the calendar to use in constructing the timestamp
1930     *
1931     * @return the column value; if the value is SQL NULL, the result is null
1932     *
1933     * @exception SQLException if a database-access error occurs.
1934     */

1935    public java.sql.Timestamp JavaDoc getTimestamp(int columnIndex, Calendar JavaDoc cal)
1936        throws SQLException JavaDoc {
1937        return getTimestampInternal(columnIndex, cal.getTimeZone());
1938    }
1939
1940    /**
1941     * Get the value of a column in the current row as a java.sql.Timestamp
1942     * object. Use the calendar to construct an appropriate millisecond value
1943     * for the Timestamp, if the underlying database doesn't store timezone
1944     * information.
1945     *
1946     * @param columnName is the SQL name of the column
1947     * @param cal the calendar to use in constructing the timestamp
1948     *
1949     * @return the column value; if the value is SQL NULL, the result is null
1950     *
1951     * @exception SQLException if a database-access error occurs.
1952     */

1953    public java.sql.Timestamp JavaDoc getTimestamp(String JavaDoc columnName, Calendar JavaDoc cal)
1954        throws SQLException JavaDoc {
1955        return getTimestamp(findColumn(columnName), cal);
1956    }
1957
1958    /**
1959     * JDBC 2.0 Return the type of this result set. The type is determined
1960     * based on the statement that created the result set.
1961     *
1962     * @return TYPE_FORWARD_ONLY, TYPE_SCROLL_INSENSITIVE, or
1963     * TYPE_SCROLL_SENSITIVE
1964     *
1965     * @exception SQLException if a database-access error occurs
1966     */

1967    public int getType() throws SQLException JavaDoc {
1968        return resultSetType;
1969    }
1970
1971    /**
1972     * @see ResultSet#getURL(int)
1973     */

1974    public URL JavaDoc getURL(int colIndex) throws SQLException JavaDoc {
1975        String JavaDoc val = getString(colIndex);
1976
1977        if (val == null) {
1978            return null;
1979        } else {
1980            try {
1981                return new URL JavaDoc(val);
1982            } catch (MalformedURLException JavaDoc mfe) {
1983                throw new SQLException JavaDoc("Malformed URL '" + val + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1984            }
1985        }
1986    }
1987
1988    /**
1989     * @see ResultSet#getURL(String)
1990     */

1991    public URL JavaDoc getURL(String JavaDoc colName) throws SQLException JavaDoc {
1992        String JavaDoc val = getString(colName);
1993
1994        if (val == null) {
1995            return null;
1996        } else {
1997            try {
1998                return new URL JavaDoc(val);
1999            } catch (MalformedURLException JavaDoc mfe) {
2000                throw new SQLException JavaDoc("Malformed URL '" + val + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2001            }
2002        }
2003    }
2004
2005    /**
2006     * A column value can also be retrieved as a stream of Unicode characters.
2007     * We implement this as a binary stream.
2008     *
2009     * @param columnIndex the first column is 1, the second is 2...
2010     *
2011     * @return a Java InputStream that delivers the database column value as a
2012     * stream of two byte Unicode characters. If the value is SQL
2013     * NULL, then the result is null
2014     *
2015     * @exception java.sql.SQLException if a database access error occurs
2016     *
2017     * @see getAsciiStream
2018     * @see getBinaryStream
2019     */

2020    public InputStream JavaDoc getUnicodeStream(int columnIndex)
2021        throws java.sql.SQLException JavaDoc {
2022        checkRowPos();
2023
2024        return getBinaryStream(columnIndex);
2025    }
2026
2027    /**
2028     * DOCUMENT ME!
2029     *
2030     * @param columnName DOCUMENT ME!
2031     *
2032     * @return DOCUMENT ME!
2033     *
2034     * @throws java.sql.SQLException DOCUMENT ME!
2035     */

2036    public InputStream JavaDoc getUnicodeStream(String JavaDoc columnName)
2037        throws java.sql.SQLException JavaDoc {
2038        return getUnicodeStream(findColumn(columnName));
2039    }
2040
2041    /**
2042     * The first warning reported by calls on this ResultSet is returned.
2043     * Subsequent ResultSet warnings will be chained to this
2044     * java.sql.SQLWarning.
2045     *
2046     * <p>
2047     * The warning chain is automatically cleared each time a new row is read.
2048     * </p>
2049     *
2050     * <p>
2051     * <B>Note:</B> This warning chain only covers warnings caused by ResultSet
2052     * methods. Any warnings caused by statement methods (such as reading OUT
2053     * parameters) will be chained on the Statement object.
2054     * </p>
2055     *
2056     * @return the first java.sql.SQLWarning or null;
2057     *
2058     * @exception java.sql.SQLException if a database access error occurs.
2059     */

2060    public java.sql.SQLWarning JavaDoc getWarnings() throws java.sql.SQLException JavaDoc {
2061        return warningChain;
2062    }
2063
2064    /**
2065     * JDBC 2.0
2066     *
2067     * <p>
2068     * Move to an absolute row number in the result set.
2069     * </p>
2070     *
2071     * <p>
2072     * If row is positive, moves to an absolute row with respect to the
2073     * beginning of the result set. The first row is row 1, the second is row
2074     * 2, etc.
2075     * </p>
2076     *
2077     * <p>
2078     * If row is negative, moves to an absolute row position with respect to
2079     * the end of result set. For example, calling absolute(-1) positions the
2080     * cursor on the last row, absolute(-2) indicates the next-to-last row,
2081     * etc.
2082     * </p>
2083     *
2084     * <p>
2085     * An attempt to position the cursor beyond the first/last row in the
2086     * result set, leaves the cursor before/after the first/last row,
2087     * respectively.
2088     * </p>
2089     *
2090     * <p>
2091     * Note: Calling absolute(1) is the same as calling first(). Calling
2092     * absolute(-1) is the same as calling last().
2093     * </p>
2094     *
2095     * @param row the row number to move to
2096     *
2097     * @return true if on the result set, false if off.
2098     *
2099     * @exception SQLException if a database-access error occurs, or row is 0,
2100     * or result set type is TYPE_FORWARD_ONLY.
2101     */

2102    public boolean absolute(int row) throws SQLException JavaDoc {
2103        if (Driver.TRACE) {
2104            Object JavaDoc[] args = { new Integer JavaDoc(row) };
2105            Debug.methodCall(this, "absolute", args);
2106        }
2107
2108        checkClosed();
2109
2110        boolean b;
2111
2112        if (rowData.size() == 0) {
2113            b = false;
2114        } else {
2115            if (row == 0) {
2116                throw new SQLException JavaDoc("Cannot absolute position to row 0",
2117                    SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2118            }
2119
2120            if (onInsertRow) {
2121                onInsertRow = false;
2122            }
2123
2124            if (doingUpdates) {
2125                doingUpdates = false;
2126            }
2127
2128            if (row == 1) {
2129                b = first();
2130            } else if (row == -1) {
2131                b = last();
2132            } else if (row > rowData.size()) {
2133                afterLast();
2134                b = false;
2135            } else {
2136                if (row < 0) {
2137                    // adjust to reflect after end of result set
2138
int newRowPosition = rowData.size() + row + 1;
2139
2140                    if (newRowPosition <= 0) {
2141                        beforeFirst();
2142                        b = false;
2143                    } else {
2144                        b = absolute(newRowPosition);
2145                    }
2146                } else {
2147                    row--; // adjust for index difference
2148
rowData.setCurrentRow(row);
2149                    thisRow = (byte[][]) rowData.getAt(row);
2150                    b = true;
2151                }
2152            }
2153        }
2154
2155        if (Driver.TRACE) {
2156            Debug.returnValue(this, "absolute", new Boolean JavaDoc(b));
2157        }
2158
2159        return b;
2160    }
2161
2162    /**
2163     * JDBC 2.0
2164     *
2165     * <p>
2166     * Moves to the end of the result set, just after the last row. Has no
2167     * effect if the result set contains no rows.
2168     * </p>
2169     *
2170     * @exception SQLException if a database-access error occurs, or result set
2171     * type is TYPE_FORWARD_ONLY.
2172     */

2173    public void afterLast() throws SQLException JavaDoc {
2174        if (Driver.TRACE) {
2175            Object JavaDoc[] args = { };
2176            Debug.methodCall(this, "afterLast", args);
2177        }
2178
2179        checkClosed();
2180
2181        if (onInsertRow) {
2182            onInsertRow = false;
2183        }
2184
2185        if (doingUpdates) {
2186            doingUpdates = false;
2187        }
2188
2189        if (rowData.size() != 0) {
2190            rowData.afterLast();
2191            thisRow = null;
2192        }
2193    }
2194
2195    /**
2196     * JDBC 2.0
2197     *
2198     * <p>
2199     * Moves to the front of the result set, just before the first row. Has no
2200     * effect if the result set contains no rows.
2201     * </p>
2202     *
2203     * @exception SQLException if a database-access error occurs, or result set
2204     * type is TYPE_FORWARD_ONLY
2205     */

2206    public void beforeFirst() throws SQLException JavaDoc {
2207        if (Driver.TRACE) {
2208            Object JavaDoc[] args = { };
2209            Debug.methodCall(this, "beforeFirst", args);
2210        }
2211
2212        checkClosed();
2213
2214        if (onInsertRow) {
2215            onInsertRow = false;
2216        }
2217
2218        if (doingUpdates) {
2219            doingUpdates = false;
2220        }
2221
2222        if (rowData.size() == 0) {
2223            return;
2224        } else {
2225            rowData.beforeFirst();
2226            thisRow = null;
2227        }
2228    }
2229
2230    /**
2231     * JDBC 2.0 The cancelRowUpdates() method may be called after calling an
2232     * updateXXX() method(s) and before calling updateRow() to rollback the
2233     * updates made to a row. If no updates have been made or updateRow() has
2234     * already been called, then this method has no effect.
2235     *
2236     * @exception SQLException if a database-access error occurs, or if called
2237     * when on the insert row.
2238     * @throws NotUpdatable DOCUMENT ME!
2239     */

2240    public void cancelRowUpdates() throws SQLException JavaDoc {
2241        throw new NotUpdatable();
2242    }
2243
2244    /**
2245     * After this call, getWarnings returns null until a new warning is
2246     * reported for this ResultSet
2247     *
2248     * @exception java.sql.SQLException if a database access error occurs
2249     */

2250    public void clearWarnings() throws java.sql.SQLException JavaDoc {
2251        warningChain = null;
2252    }
2253
2254    /**
2255     * In some cases, it is desirable to immediately release a ResultSet
2256     * database and JDBC resources instead of waiting for this to happen when
2257     * it is automatically closed. The close method provides this immediate
2258     * release.
2259     *
2260     * <p>
2261     * <B>Note:</B> A ResultSet is automatically closed by the Statement the
2262     * Statement that generated it when that Statement is closed, re-executed,
2263     * or is used to retrieve the next result from a sequence of multiple
2264     * results. A ResultSet is also automatically closed when it is garbage
2265     * collected.
2266     * </p>
2267     *
2268     * @exception java.sql.SQLException if a database access error occurs
2269     */

2270    public void close() throws java.sql.SQLException JavaDoc {
2271        realClose(true);
2272    }
2273
2274    /**
2275     * JDBC 2.0 Delete the current row from the result set and the underlying
2276     * database. Cannot be called when on the insert row.
2277     *
2278     * @exception SQLException if a database-access error occurs, or if called
2279     * when on the insert row.
2280     * @throws NotUpdatable DOCUMENT ME!
2281     */

2282    public void deleteRow() throws SQLException JavaDoc {
2283        throw new NotUpdatable();
2284    }
2285
2286    /**
2287     * Map a ResultSet column name to a ResultSet column index
2288     *
2289     * @param columnName the name of the column
2290     *
2291     * @return the column index
2292     *
2293     * @exception java.sql.SQLException if a database access error occurs
2294     */

2295    public int findColumn(String JavaDoc columnName) throws java.sql.SQLException JavaDoc {
2296        Integer JavaDoc index;
2297
2298        synchronized (this) {
2299            if (!hasBuiltIndexMapping) {
2300                buildIndexMapping();
2301            }
2302        }
2303
2304        index = (Integer JavaDoc) columnNameToIndex.get(columnName);
2305
2306        if (index == null) {
2307            index = (Integer JavaDoc) fullColumnNameToIndex.get(columnName);
2308        }
2309
2310        if (index != null) {
2311            return index.intValue() + 1;
2312        } else {
2313            // Try this inefficient way, now
2314
String JavaDoc columnNameUC = columnName.toUpperCase();
2315
2316            for (int i = 0; i < fields.length; i++) {
2317                if (fields[i].getName().toUpperCase().equals(columnNameUC)) {
2318                    return i + 1;
2319                } else if (fields[i].getFullName().toUpperCase().equals(columnNameUC)) {
2320                    return i + 1;
2321                }
2322            }
2323
2324            throw new java.sql.SQLException JavaDoc("Column '" + columnName
2325                + "' not found.", SQLError.SQL_STATE_COLUMN_NOT_FOUND);
2326        }
2327    }
2328
2329    /**
2330     * JDBC 2.0
2331     *
2332     * <p>
2333     * Moves to the first row in the result set.
2334     * </p>
2335     *
2336     * @return true if on a valid row, false if no rows in the result set.
2337     *
2338     * @exception SQLException if a database-access error occurs, or result set
2339     * type is TYPE_FORWARD_ONLY.
2340     */

2341    public boolean first() throws SQLException JavaDoc {
2342        if (Driver.TRACE) {
2343            Object JavaDoc[] args = { };
2344            Debug.methodCall(this, "first", args);
2345        }
2346
2347        checkClosed();
2348
2349        if (onInsertRow) {
2350            onInsertRow = false;
2351        }
2352
2353        if (rowData.isEmpty()) {
2354            return false;
2355        } else {
2356            if (doingUpdates) {
2357                doingUpdates = false;
2358            }
2359
2360            rowData.beforeFirst();
2361            thisRow = rowData.next();
2362
2363            return true;
2364        }
2365    }
2366
2367    /**
2368     * JDBC 2.0 Insert the contents of the insert row into the result set and
2369     * the database. Must be on the insert row when this method is called.
2370     *
2371     * @exception SQLException if a database-access error occurs, if called
2372     * when not on the insert row, or if all non-nullable columns
2373     * in the insert row have not been given a value
2374     * @throws NotUpdatable DOCUMENT ME!
2375     */

2376    public void insertRow() throws SQLException JavaDoc {
2377        throw new NotUpdatable();
2378    }
2379
2380    /**
2381     * JDBC 2.0
2382     *
2383     * <p>
2384     * Moves to the last row in the result set.
2385     * </p>
2386     *
2387     * @return true if on a valid row, false if no rows in the result set.
2388     *
2389     * @exception SQLException if a database-access error occurs, or result set
2390     * type is TYPE_FORWARD_ONLY.
2391     */

2392    public boolean last() throws SQLException JavaDoc {
2393        if (Driver.TRACE) {
2394            Object JavaDoc[] args = { };
2395            Debug.methodCall(this, "last", args);
2396        }
2397
2398        checkClosed();
2399
2400        if (rowData.size() == 0) {
2401            return false;
2402        } else {
2403            if (onInsertRow) {
2404                onInsertRow = false;
2405            }
2406
2407            if (doingUpdates) {
2408                doingUpdates = false;
2409            }
2410
2411            rowData.beforeLast();
2412            thisRow = rowData.next();
2413
2414            return true;
2415        }
2416    }
2417
2418    /**
2419     * JDBC 2.0 Move the cursor to the remembered cursor position, usually the
2420     * current row. Has no effect unless the cursor is on the insert row.
2421     *
2422     * @exception SQLException if a database-access error occurs, or the result
2423     * set is not updatable
2424     * @throws NotUpdatable DOCUMENT ME!
2425     */

2426    public void moveToCurrentRow() throws SQLException JavaDoc {
2427        throw new NotUpdatable();
2428    }
2429
2430    /**
2431     * JDBC 2.0 Move to the insert row. The current cursor position is
2432     * remembered while the cursor is positioned on the insert row. The insert
2433     * row is a special row associated with an updatable result set. It is
2434     * essentially a buffer where a new row may be constructed by calling the
2435     * updateXXX() methods prior to inserting the row into the result set.
2436     * Only the updateXXX(), getXXX(), and insertRow() methods may be called
2437     * when the cursor is on the insert row. All of the columns in a result
2438     * set must be given a value each time this method is called before
2439     * calling insertRow(). UpdateXXX()must be called before getXXX() on a
2440     * column.
2441     *
2442     * @exception SQLException if a database-access error occurs, or the result
2443     * set is not updatable
2444     * @throws NotUpdatable DOCUMENT ME!
2445     */

2446    public void moveToInsertRow() throws SQLException JavaDoc {
2447        throw new NotUpdatable();
2448    }
2449
2450    /**
2451     * A ResultSet is initially positioned before its first row, the first call
2452     * to next makes the first row the current row; the second call makes the
2453     * second row the current row, etc.
2454     *
2455     * <p>
2456     * If an input stream from the previous row is open, it is implicitly
2457     * closed. The ResultSet's warning chain is cleared when a new row is
2458     * read
2459     * </p>
2460     *
2461     * @return true if the new current is valid; false if there are no more
2462     * rows
2463     *
2464     * @exception java.sql.SQLException if a database access error occurs
2465     */

2466    public boolean next() throws java.sql.SQLException JavaDoc {
2467        if (Driver.TRACE) {
2468            Object JavaDoc[] args = { };
2469            Debug.methodCall(this, "next", args);
2470        }
2471
2472        checkClosed();
2473
2474        if (onInsertRow) {
2475            onInsertRow = false;
2476        }
2477
2478        if (doingUpdates) {
2479            doingUpdates = false;
2480        }
2481
2482        boolean b;
2483
2484        if (!reallyResult()) {
2485            throw new java.sql.SQLException JavaDoc("ResultSet is from UPDATE. No Data",
2486                SQLError.SQL_STATE_GENERAL_ERROR);
2487        }
2488
2489        if (rowData.size() == 0) {
2490            b = false;
2491        } else {
2492            if (!rowData.hasNext()) {
2493                // force scroll past end
2494
rowData.next();
2495                b = false;
2496            } else {
2497                clearWarnings();
2498                thisRow = rowData.next();
2499                b = true;
2500            }
2501        }
2502
2503        if (Driver.TRACE) {
2504            Debug.returnValue(this, "next", new Boolean JavaDoc(b));
2505        }
2506
2507        return b;
2508    }
2509
2510    /**
2511     * The prev method is not part of JDBC, but because of the architecture of
2512     * this driver it is possible to move both forward and backward within the
2513     * result set.
2514     *
2515     * <p>
2516     * If an input stream from the previous row is open, it is implicitly
2517     * closed. The ResultSet's warning chain is cleared when a new row is
2518     * read
2519     * </p>
2520     *
2521     * @return true if the new current is valid; false if there are no more
2522     * rows
2523     *
2524     * @exception java.sql.SQLException if a database access error occurs
2525     */

2526    public boolean prev() throws java.sql.SQLException JavaDoc {
2527        checkClosed();
2528
2529        int rowIndex = rowData.getCurrentRowNumber();
2530
2531        if ((rowIndex - 1) >= 0) {
2532            rowIndex--;
2533            rowData.setCurrentRow(rowIndex);
2534            thisRow = (byte[][]) rowData.getAt(rowIndex);
2535
2536            return true;
2537        } else if ((rowIndex - 1) == -1) {
2538            rowIndex--;
2539            rowData.setCurrentRow(rowIndex);
2540            thisRow = null;
2541
2542            return false;
2543        } else {
2544            return false;
2545        }
2546    }
2547
2548    /**
2549     * JDBC 2.0
2550     *
2551     * <p>
2552     * Moves to the previous row in the result set.
2553     * </p>
2554     *
2555     * <p>
2556     * Note: previous() is not the same as relative(-1) since it makes sense to
2557     * call previous() when there is no current row.
2558     * </p>
2559     *
2560     * @return true if on a valid row, false if off the result set.
2561     *
2562     * @exception SQLException if a database-access error occurs, or result set
2563     * type is TYPE_FORWAR_DONLY.
2564     */

2565    public boolean previous() throws SQLException JavaDoc {
2566        if (Driver.TRACE) {
2567            Object JavaDoc[] args = { };
2568            Debug.methodCall(this, "previous", args);
2569        }
2570
2571        if (onInsertRow) {
2572            onInsertRow = false;
2573        }
2574
2575        if (doingUpdates) {
2576            doingUpdates = false;
2577        }
2578
2579        return prev();
2580    }
2581
2582    /**
2583     * JDBC 2.0 Refresh the value of the current row with its current value in
2584     * the database. Cannot be called when on the insert row. The
2585     * refreshRow() method provides a way for an application to explicitly
2586     * tell the JDBC driver to refetch a row(s) from the database. An
2587     * application may want to call refreshRow() when caching or prefetching
2588     * is being done by the JDBC driver to fetch the latest value of a row
2589     * from the database. The JDBC driver may actually refresh multiple rows
2590     * at once if the fetch size is greater than one. All values are refetched
2591     * subject to the transaction isolation level and cursor sensitivity. If
2592     * refreshRow() is called after calling updateXXX(), but before calling
2593     * updateRow() then the updates made to the row are lost. Calling
2594     * refreshRow() frequently will likely slow performance.
2595     *
2596     * @exception SQLException if a database-access error occurs, or if called
2597     * when on the insert row.
2598     * @throws NotUpdatable DOCUMENT ME!
2599     */

2600    public void refreshRow() throws SQLException JavaDoc {
2601        throw new NotUpdatable();
2602    }
2603
2604    /**
2605     * JDBC 2.0
2606     *
2607     * <p>
2608     * Moves a relative number of rows, either positive or negative. Attempting
2609     * to move beyond the first/last row in the result set positions the
2610     * cursor before/after the the first/last row. Calling relative(0) is
2611     * valid, but does not change the cursor position.
2612     * </p>
2613     *
2614     * <p>
2615     * Note: Calling relative(1) is different than calling next() since is
2616     * makes sense to call next() when there is no current row, for example,
2617     * when the cursor is positioned before the first row or after the last
2618     * row of the result set.
2619     * </p>
2620     *
2621     * @param rows the number of relative rows to move the cursor.
2622     *
2623     * @return true if on a row, false otherwise.
2624     *
2625     * @throws SQLException if a database-access error occurs, or there is no
2626     * current row, or result set type is TYPE_FORWARD_ONLY.
2627     */

2628    public boolean relative(int rows) throws SQLException JavaDoc {
2629        if (Driver.TRACE) {
2630            Object JavaDoc[] args = { new Integer JavaDoc(rows) };
2631            Debug.methodCall(this, "relative", args);
2632        }
2633
2634        checkClosed();
2635
2636        if (rowData.size() == 0) {
2637            return false;
2638        }
2639
2640        rowData.moveRowRelative(rows);
2641        thisRow = rowData.getAt(rowData.getCurrentRowNumber());
2642
2643        boolean b = (!rowData.isAfterLast() && !rowData.isBeforeFirst());
2644
2645        if (Driver.TRACE) {
2646            Debug.returnValue(this, "relative", new Boolean JavaDoc(b));
2647        }
2648
2649        return b;
2650    }
2651
2652    /**
2653     * JDBC 2.0 Determine if this row has been deleted. A deleted row may
2654     * leave a visible "hole" in a result set. This method can be used to
2655     * detect holes in a result set. The value returned depends on whether or
2656     * not the result set can detect deletions.
2657     *
2658     * @return true if deleted and deletes are detected
2659     *
2660     * @exception SQLException if a database-access error occurs
2661     * @throws NotImplemented DOCUMENT ME!
2662     *
2663     * @see DatabaseMetaData#deletesAreDetected
2664     */

2665    public boolean rowDeleted() throws SQLException JavaDoc {
2666        throw new NotImplemented();
2667    }
2668
2669    /**
2670     * JDBC 2.0 Determine if the current row has been inserted. The value
2671     * returned depends on whether or not the result set can detect visible
2672     * inserts.
2673     *
2674     * @return true if inserted and inserts are detected
2675     *
2676     * @exception SQLException if a database-access error occurs
2677     * @throws NotImplemented DOCUMENT ME!
2678     *
2679     * @see DatabaseMetaData#insertsAreDetected
2680     */

2681    public boolean rowInserted() throws SQLException JavaDoc {
2682        throw new NotImplemented();
2683    }
2684
2685    //---------------------------------------------------------------------
2686
// Updates
2687
//---------------------------------------------------------------------
2688

2689    /**
2690     * JDBC 2.0 Determine if the current row has been updated. The value
2691     * returned depends on whether or not the result set can detect updates.
2692     *
2693     * @return true if the row has been visibly updated by the owner or
2694     * another, and updates are detected
2695     *
2696     * @exception SQLException if a database-access error occurs
2697     * @throws NotImplemented DOCUMENT ME!
2698     *
2699     * @see DatabaseMetaData#updatesAreDetected
2700     */

2701    public boolean rowUpdated() throws SQLException JavaDoc {
2702        throw new NotImplemented();
2703    }
2704
2705    /**
2706     * @see ResultSet#updateArray(int, Array)
2707     */

2708    public void updateArray(int arg0, Array JavaDoc arg1) throws SQLException JavaDoc {
2709        throw new NotImplemented();
2710    }
2711
2712    /**
2713     * @see ResultSet#updateArray(String, Array)
2714     */

2715    public void updateArray(String JavaDoc arg0, Array JavaDoc arg1) throws SQLException JavaDoc {
2716        throw new NotImplemented();
2717    }
2718
2719    /**
2720     * JDBC 2.0 Update a column with an ascii stream value. The updateXXX()
2721     * methods are used to update column values in the current row, or the
2722     * insert row. The updateXXX() methods do not update the underlying
2723     * database, instead the updateRow() or insertRow() methods are called to
2724     * update the database.
2725     *
2726     * @param columnIndex the first column is 1, the second is 2, ...
2727     * @param x the new column value
2728     * @param length the length of the stream
2729     *
2730     * @exception SQLException if a database-access error occurs
2731     * @throws NotUpdatable DOCUMENT ME!
2732     */

2733    public void updateAsciiStream(int columnIndex, java.io.InputStream JavaDoc x,
2734        int length) throws SQLException JavaDoc {
2735        throw new NotUpdatable();
2736    }
2737
2738    /**
2739     * JDBC 2.0 Update a column with an ascii stream value. The updateXXX()
2740     * methods are used to update column values in the current row, or the
2741     * insert row. The updateXXX() methods do not update the underlying
2742     * database, instead the updateRow() or insertRow() methods are called to
2743     * update the database.
2744     *
2745     * @param columnName the name of the column
2746     * @param x the new column value
2747     * @param length of the stream
2748     *
2749     * @exception SQLException if a database-access error occurs
2750     */

2751    public void updateAsciiStream(String JavaDoc columnName, java.io.InputStream JavaDoc x,
2752        int length) throws SQLException JavaDoc {
2753        updateAsciiStream(findColumn(columnName), x, length);
2754    }
2755
2756    /**
2757     * JDBC 2.0 Update a column with a BigDecimal value. The updateXXX()
2758     * methods are used to update column values in the current row, or the
2759     * insert row. The updateXXX() methods do not update the underlying
2760     * database, instead the updateRow() or insertRow() methods are called to
2761     * update the database.
2762     *
2763     * @param columnIndex the first column is 1, the second is 2, ...
2764     * @param x the new column value
2765     *
2766     * @exception SQLException if a database-access error occurs
2767     * @throws NotUpdatable DOCUMENT ME!
2768     */

2769    public void updateBigDecimal(int columnIndex, BigDecimal JavaDoc x)
2770        throws SQLException JavaDoc {
2771        throw new NotUpdatable();
2772    }
2773
2774    /**
2775     * JDBC 2.0 Update a column with a BigDecimal value. The updateXXX()
2776     * methods are used to update column values in the current row, or the
2777     * insert row. The updateXXX() methods do not update the underlying
2778     * database, instead the updateRow() or insertRow() methods are called to
2779     * update the database.
2780     *
2781     * @param columnName the name of the column
2782     * @param x the new column value
2783     *
2784     * @exception SQLException if a database-access error occurs
2785     */

2786    public void updateBigDecimal(String JavaDoc columnName, BigDecimal JavaDoc x)
2787        throws SQLException JavaDoc {
2788        updateBigDecimal(findColumn(columnName), x);
2789    }
2790
2791    /**
2792     * JDBC 2.0 Update a column with a binary stream value. The updateXXX()
2793     * methods are used to update column values in the current row, or the
2794     * insert row. The updateXXX() methods do not update the underlying
2795     * database, instead the updateRow() or insertRow() methods are called to
2796     * update the database.
2797     *
2798     * @param columnIndex the first column is 1, the second is 2, ...
2799     * @param x the new column value
2800     * @param length the length of the stream
2801     *
2802     * @exception SQLException if a database-access error occurs
2803     * @throws NotUpdatable DOCUMENT ME!
2804     */

2805    public void updateBinaryStream(int columnIndex, java.io.InputStream JavaDoc x,
2806        int length) throws SQLException JavaDoc {
2807        throw new NotUpdatable();
2808    }
2809
2810    /**
2811     * JDBC 2.0 Update a column with a binary stream value. The updateXXX()
2812     * methods are used to update column values in the current row, or the
2813     * insert row. The updateXXX() methods do not update the underlying
2814     * database, instead the updateRow() or insertRow() methods are called to
2815     * update the database.
2816     *
2817     * @param columnName the name of the column
2818     * @param x the new column value
2819     * @param length of the stream
2820     *
2821     * @exception SQLException if a database-access error occurs
2822     */

2823    public void updateBinaryStream(String JavaDoc columnName, java.io.InputStream JavaDoc x,
2824        int length) throws SQLException JavaDoc {
2825        updateBinaryStream(findColumn(columnName), x, length);
2826    }
2827
2828    /**
2829     * @see ResultSet#updateBlob(int, Blob)
2830     */

2831    public void updateBlob(int arg0, java.sql.Blob JavaDoc arg1)
2832        throws SQLException JavaDoc {
2833        throw new NotUpdatable();
2834    }
2835
2836    /**
2837     * @see ResultSet#updateBlob(String, Blob)
2838     */

2839    public void updateBlob(String JavaDoc arg0, java.sql.Blob JavaDoc arg1)
2840        throws SQLException JavaDoc {
2841        throw new NotUpdatable();
2842    }
2843
2844    /**
2845     * JDBC 2.0 Update a column with a boolean value. The updateXXX() methods
2846     * are used to update column values in the current row, or the insert row.
2847     * The updateXXX() methods do not update the underlying database, instead
2848     * the updateRow() or insertRow() methods are called to update the
2849     * database.
2850     *
2851     * @param columnIndex the first column is 1, the second is 2, ...
2852     * @param x the new column value
2853     *
2854     * @exception SQLException if a database-access error occurs
2855     * @throws NotUpdatable DOCUMENT ME!
2856     */

2857    public void updateBoolean(int columnIndex, boolean x)
2858        throws SQLException JavaDoc {
2859        throw new NotUpdatable();
2860    }
2861
2862    /**
2863     * JDBC 2.0 Update a column with a boolean value. The updateXXX() methods
2864     * are used to update column values in the current row, or the insert row.
2865     * The updateXXX() methods do not update the underlying database, instead
2866     * the updateRow() or insertRow() methods are called to update the
2867     * database.
2868     *
2869     * @param columnName the name of the column
2870     * @param x the new column value
2871     *
2872     * @exception SQLException if a database-access error occurs
2873     */

2874    public void updateBoolean(String JavaDoc columnName, boolean x)
2875        throws SQLException JavaDoc {
2876        updateBoolean(findColumn(columnName), x);
2877    }
2878
2879    /**
2880     * JDBC 2.0 Update a column with a byte value. The updateXXX() methods are
2881     * used to update column values in the current row, or the insert row. The
2882     * updateXXX() methods do not update the underlying database, instead the
2883     * updateRow() or insertRow() methods are called to update the database.
2884     *
2885     * @param columnIndex the first column is 1, the second is 2, ...
2886     * @param x the new column value
2887     *
2888     * @exception SQLException if a database-access error occurs
2889     * @throws NotUpdatable DOCUMENT ME!
2890     */

2891    public void updateByte(int columnIndex, byte x) throws SQLException JavaDoc {
2892        throw new NotUpdatable();
2893    }
2894
2895    /**
2896     * JDBC 2.0 Update a column with a byte value. The updateXXX() methods are
2897     * used to update column values in the current row, or the insert row. The
2898     * updateXXX() methods do not update the underlying database, instead the
2899     * updateRow() or insertRow() methods are called to update the database.
2900     *
2901     * @param columnName the name of the column
2902     * @param x the new column value
2903     *
2904     * @exception SQLException if a database-access error occurs
2905     */

2906    public void updateByte(String JavaDoc columnName, byte x) throws SQLException JavaDoc {
2907        updateByte(findColumn(columnName), x);
2908    }
2909
2910    /**
2911     * JDBC 2.0 Update a column with a byte array value. The updateXXX()
2912     * methods are used to update column values in the current row, or the
2913     * insert row. The updateXXX() methods do not update the underlying
2914     * database, instead the updateRow() or insertRow() methods are called to
2915     * update the database.
2916     *
2917     * @param columnIndex the first column is 1, the second is 2, ...
2918     * @param x the new column value
2919     *
2920     * @exception SQLException if a database-access error occurs
2921     * @throws NotUpdatable DOCUMENT ME!
2922     */

2923    public void updateBytes(int columnIndex, byte[] x)
2924        throws SQLException JavaDoc {
2925        throw new NotUpdatable();
2926    }
2927
2928    /**
2929     * JDBC 2.0 Update a column with a byte array value. The updateXXX()
2930     * methods are used to update column values in the current row, or the
2931     * insert row. The updateXXX() methods do not update the underlying
2932     * database, instead the updateRow() or insertRow() methods are called to
2933     * update the database.
2934     *
2935     * @param columnName the name of the column
2936     * @param x the new column value
2937     *
2938     * @exception SQLException if a database-access error occurs
2939     */

2940    public void updateBytes(String JavaDoc columnName, byte[] x)
2941        throws SQLException JavaDoc {
2942        updateBytes(findColumn(columnName), x);
2943    }
2944
2945    /**
2946     * JDBC 2.0 Update a column with a character stream value. The updateXXX()
2947     * methods are used to update column values in the current row, or the
2948     * insert row. The updateXXX() methods do not update the underlying
2949     * database, instead the updateRow() or insertRow() methods are called to
2950     * update the database.
2951     *
2952     * @param columnIndex the first column is 1, the second is 2, ...
2953     * @param x the new column value
2954     * @param length the length of the stream
2955     *
2956     * @exception SQLException if a database-access error occurs
2957     * @throws NotUpdatable DOCUMENT ME!
2958     */

2959    public void updateCharacterStream(int columnIndex, java.io.Reader JavaDoc x,
2960        int length) throws SQLException JavaDoc {
2961        throw new NotUpdatable();
2962    }
2963
2964    /**
2965     * JDBC 2.0 Update a column with a character stream value. The updateXXX()
2966     * methods are used to update column values in the current row, or the
2967     * insert row. The updateXXX() methods do not update the underlying
2968     * database, instead the updateRow() or insertRow() methods are called to
2969     * update the database.
2970     *
2971     * @param columnName the name of the column
2972     * @param reader the stream to update the column with
2973     * @param length of the stream
2974     *
2975     * @throws SQLException if a database-access error occurs
2976     */

2977    public void updateCharacterStream(String JavaDoc columnName, java.io.Reader JavaDoc reader,
2978        int length) throws SQLException JavaDoc {
2979        updateCharacterStream(findColumn(columnName), reader, length);
2980    }
2981
2982    /**
2983     * @see ResultSet#updateClob(int, Clob)
2984     */

2985    public void updateClob(int arg0, java.sql.Clob JavaDoc arg1) throws SQLException JavaDoc {
2986        throw new NotUpdatable();
2987    }
2988
2989    /**
2990     * @see ResultSet#updateClob(String, Clob)
2991     */

2992    public void updateClob(String JavaDoc columnName, java.sql.Clob JavaDoc clob) throws SQLException JavaDoc {
2993        updateClob(findColumn(columnName), clob);
2994    }
2995
2996    /**
2997     * JDBC 2.0 Update a column with a Date value. The updateXXX() methods are
2998     * used to update column values in the current row, or the insert row. The
2999     * updateXXX() methods do not update the underlying database, instead the
3000     * updateRow() or insertRow() methods are called to update the database.
3001     *
3002     * @param columnIndex the first column is 1, the second is 2, ...
3003     * @param x the new column value
3004     *
3005     * @exception SQLException if a database-access error occurs
3006     * @throws NotUpdatable DOCUMENT ME!
3007     */

3008    public void updateDate(int columnIndex, java.sql.Date JavaDoc x)
3009        throws SQLException JavaDoc {
3010        throw new NotUpdatable();
3011    }
3012
3013    /**
3014     * JDBC 2.0 Update a column with a Date value. The updateXXX() methods are
3015     * used to update column values in the current row, or the insert row. The
3016     * updateXXX() methods do not update the underlying database, instead the
3017     * updateRow() or insertRow() methods are called to update the database.
3018     *
3019     * @param columnName the name of the column
3020     * @param x the new column value
3021     *
3022     * @exception SQLException if a database-access error occurs
3023     */

3024    public void updateDate(String JavaDoc columnName, java.sql.Date JavaDoc x)
3025        throws SQLException JavaDoc {
3026        updateDate(findColumn(columnName), x);
3027    }
3028
3029    /**
3030     * JDBC 2.0 Update a column with a Double value. The updateXXX() methods
3031     * are used to update column values in the current row, or the insert row.
3032     * The updateXXX() methods do not update the underlying database, instead
3033     * the updateRow() or insertRow() methods are called to update the
3034     * database.
3035     *
3036     * @param columnIndex the first column is 1, the second is 2, ...
3037     * @param x the new column value
3038     *
3039     * @exception SQLException if a database-access error occurs
3040     * @throws NotUpdatable DOCUMENT ME!
3041     */

3042    public void updateDouble(int columnIndex, double x)
3043        throws SQLException JavaDoc {
3044        throw new NotUpdatable();
3045    }
3046
3047    /**
3048     * JDBC 2.0 Update a column with a double value. The updateXXX() methods
3049     * are used to update column values in the current row, or the insert row.
3050     * The updateXXX() methods do not update the underlying database, instead
3051     * the updateRow() or insertRow() methods are called to update the
3052     * database.
3053     *
3054     * @param columnName the name of the column
3055     * @param x the new column value
3056     *
3057     * @exception SQLException if a database-access error occurs
3058     */

3059    public void updateDouble(String JavaDoc columnName, double x)
3060        throws SQLException JavaDoc {
3061        updateDouble(findColumn(columnName), x);
3062    }
3063
3064    /**
3065     * JDBC 2.0 Update a column with a float value. The updateXXX() methods are
3066     * used to update column values in the current row, or the insert row. The
3067     * updateXXX() methods do not update the underlying database, instead the
3068     * updateRow() or insertRow() methods are called to update the database.
3069     *
3070     * @param columnIndex the first column is 1, the second is 2, ...
3071     * @param x the new column value
3072     *
3073     * @exception SQLException if a database-access error occurs
3074     * @throws NotUpdatable DOCUMENT ME!
3075     */

3076    public void updateFloat(int columnIndex, float x) throws SQLException JavaDoc {
3077        throw new NotUpdatable();
3078    }
3079
3080    /**
3081     * JDBC 2.0 Update a column with a float value. The updateXXX() methods are
3082     * used to update column values in the current row, or the insert row. The
3083     * updateXXX() methods do not update the underlying database, instead the
3084     * updateRow() or insertRow() methods are called to update the database.
3085     *
3086     * @param columnName the name of the column
3087     * @param x the new column value
3088     *
3089     * @exception SQLException if a database-access error occurs
3090     */

3091    public void updateFloat(String JavaDoc columnName, float x)
3092        throws SQLException JavaDoc {
3093        updateFloat(findColumn(columnName), x);
3094    }
3095
3096    /**
3097     * JDBC 2.0 Update a column with an integer value. The updateXXX() methods
3098     * are used to update column values in the current row, or the insert row.
3099     * The updateXXX() methods do not update the underlying database, instead
3100     * the updateRow() or insertRow() methods are called to update the
3101     * database.
3102     *
3103     * @param columnIndex the first column is 1, the second is 2, ...
3104     * @param x the new column value
3105     *
3106     * @exception SQLException if a database-access error occurs
3107     * @throws NotUpdatable DOCUMENT ME!
3108     */

3109    public void updateInt(int columnIndex, int x) throws SQLException JavaDoc {
3110        throw new NotUpdatable();
3111    }
3112
3113    /**
3114     * JDBC 2.0 Update a column with an integer value. The updateXXX() methods
3115     * are used to update column values in the current row, or the insert row.
3116     * The updateXXX() methods do not update the underlying database, instead
3117     * the updateRow() or insertRow() methods are called to update the
3118     * database.
3119     *
3120     * @param columnName the name of the column
3121     * @param x the new column value
3122     *
3123     * @exception SQLException if a database-access error occurs
3124     */

3125    public void updateInt(String JavaDoc columnName, int x) throws SQLException JavaDoc {
3126        updateInt(findColumn(columnName), x);
3127    }
3128
3129    /**
3130     * JDBC 2.0 Update a column with a long value. The updateXXX() methods are
3131     * used to update column values in the current row, or the insert row. The
3132     * updateXXX() methods do not update the underlying database, instead the
3133     * updateRow() or insertRow() methods are called to update the database.
3134     *
3135     * @param columnIndex the first column is 1, the second is 2, ...
3136     * @param x the new column value
3137     *
3138     * @exception SQLException if a database-access error occurs
3139     * @throws NotUpdatable DOCUMENT ME!
3140     */

3141    public void updateLong(int columnIndex, long x) throws SQLException JavaDoc {
3142        throw new NotUpdatable();
3143    }
3144
3145    /**
3146     * JDBC 2.0 Update a column with a long value. The updateXXX() methods are
3147     * used to update column values in the current row, or the insert row. The
3148     * updateXXX() methods do not update the underlying database, instead the
3149     * updateRow() or insertRow() methods are called to update the database.
3150     *
3151     * @param columnName the name of the column
3152     * @param x the new column value
3153     *
3154     * @exception SQLException if a database-access error occurs
3155     */

3156    public void updateLong(String JavaDoc columnName, long x) throws SQLException JavaDoc {
3157        updateLong(findColumn(columnName), x);
3158    }
3159
3160    /**
3161     * JDBC 2.0 Give a nullable column a null value. The updateXXX() methods
3162     * are used to update column values in the current row, or the insert row.
3163     * The updateXXX() methods do not update the underlying database, instead
3164     * the updateRow() or insertRow() methods are called to update the
3165     * database.
3166     *
3167     * @param columnIndex the first column is 1, the second is 2, ...
3168     *
3169     * @exception SQLException if a database-access error occurs
3170     * @throws NotUpdatable DOCUMENT ME!
3171     */

3172    public void updateNull(int columnIndex) throws SQLException JavaDoc {
3173        throw new NotUpdatable();
3174    }
3175
3176    /**
3177     * JDBC 2.0 Update a column with a null value. The updateXXX() methods are
3178     * used to update column values in the current row, or the insert row. The
3179     * updateXXX() methods do not update the underlying database, instead the
3180     * updateRow() or insertRow() methods are called to update the database.
3181     *
3182     * @param columnName the name of the column
3183     *
3184     * @exception SQLException if a database-access error occurs
3185     */

3186    public void updateNull(String JavaDoc columnName) throws SQLException JavaDoc {
3187        updateNull(findColumn(columnName));
3188    }
3189
3190    /**
3191     * JDBC 2.0 Update a column with an Object value. The updateXXX() methods
3192     * are used to update column values in the current row, or the insert row.
3193     * The updateXXX() methods do not update the underlying database, instead
3194     * the updateRow() or insertRow() methods are called to update the
3195     * database.
3196     *
3197     * @param columnIndex the first column is 1, the second is 2, ...
3198     * @param x the new column value
3199     * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
3200     * this is the number of digits after the decimal. For all other
3201     * types this value will be ignored.
3202     *
3203     * @exception SQLException if a database-access error occurs
3204     * @throws NotUpdatable DOCUMENT ME!
3205     */

3206    public void updateObject(int columnIndex, Object JavaDoc x, int scale)
3207        throws SQLException JavaDoc {
3208        throw new NotUpdatable();
3209    }
3210
3211    /**
3212     * JDBC 2.0 Update a column with an Object value. The updateXXX() methods
3213     * are used to update column values in the current row, or the insert row.
3214     * The updateXXX() methods do not update the underlying database, instead
3215     * the updateRow() or insertRow() methods are called to update the
3216     * database.
3217     *
3218     * @param columnIndex the first column is 1, the second is 2, ...
3219     * @param x the new column value
3220     *
3221     * @exception SQLException if a database-access error occurs
3222     * @throws NotUpdatable DOCUMENT ME!
3223     */

3224    public void updateObject(int columnIndex, Object JavaDoc x)
3225        throws SQLException JavaDoc {
3226        throw new NotUpdatable();
3227    }
3228
3229    /**
3230     * JDBC 2.0 Update a column with an Object value. The updateXXX() methods
3231     * are used to update column values in the current row, or the insert row.
3232     * The updateXXX() methods do not update the underlying database, instead
3233     * the updateRow() or insertRow() methods are called to update the
3234     * database.
3235     *
3236     * @param columnName the name of the column
3237     * @param x the new column value
3238     * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
3239     * this is the number of digits after the decimal. For all other
3240     * types this value will be ignored.
3241     *
3242     * @exception SQLException if a database-access error occurs
3243     */

3244    public void updateObject(String JavaDoc columnName, Object JavaDoc x, int scale)
3245        throws SQLException JavaDoc {
3246        updateObject(findColumn(columnName), x);
3247    }
3248
3249    /**
3250     * JDBC 2.0 Update a column with an Object value. The updateXXX() methods
3251     * are used to update column values in the current row, or the insert row.
3252     * The updateXXX() methods do not update the underlying database, instead
3253     * the updateRow() or insertRow() methods are called to update the
3254     * database.
3255     *
3256     * @param columnName the name of the column
3257     * @param x the new column value
3258     *
3259     * @exception SQLException if a database-access error occurs
3260     */

3261    public void updateObject(String JavaDoc columnName, Object JavaDoc x)
3262        throws SQLException JavaDoc {
3263        updateObject(findColumn(columnName), x);
3264    }
3265
3266    /**
3267     * @see ResultSet#updateRef(int, Ref)
3268     */

3269    public void updateRef(int arg0, Ref JavaDoc arg1) throws SQLException JavaDoc {
3270        throw new NotImplemented();
3271    }
3272
3273    /**
3274     * @see ResultSet#updateRef(String, Ref)
3275     */

3276    public void updateRef(String JavaDoc arg0, Ref JavaDoc arg1) throws SQLException JavaDoc {
3277        throw new NotImplemented();
3278    }
3279
3280    /**
3281     * JDBC 2.0 Update the underlying database with the new contents of the
3282     * current row. Cannot be called when on the insert row.
3283     *
3284     * @exception SQLException if a database-access error occurs, or if called
3285     * when on the insert row
3286     * @throws NotUpdatable DOCUMENT ME!
3287     */

3288    public void updateRow() throws SQLException JavaDoc {
3289        throw new NotUpdatable();
3290    }
3291
3292    /**
3293     * JDBC 2.0 Update a column with a short value. The updateXXX() methods are
3294     * used to update column values in the current row, or the insert row. The
3295     * updateXXX() methods do not update the underlying database, instead the
3296     * updateRow() or insertRow() methods are called to update the database.
3297     *
3298     * @param columnIndex the first column is 1, the second is 2, ...
3299     * @param x the new column value
3300     *
3301     * @exception SQLException if a database-access error occurs
3302     * @throws NotUpdatable DOCUMENT ME!
3303     */

3304    public void updateShort(int columnIndex, short x) throws SQLException JavaDoc {
3305        throw new NotUpdatable();
3306    }
3307
3308    /**
3309     * JDBC 2.0 Update a column with a short value. The updateXXX() methods are
3310     * used to update column values in the current row, or the insert row. The
3311     * updateXXX() methods do not update the underlying database, instead the
3312     * updateRow() or insertRow() methods are called to update the database.
3313     *
3314     * @param columnName the name of the column
3315     * @param x the new column value
3316     *
3317     * @exception SQLException if a database-access error occurs
3318     */

3319    public void updateShort(String JavaDoc columnName, short x)
3320        throws SQLException JavaDoc {
3321        updateShort(findColumn(columnName), x);
3322    }
3323
3324    /**
3325     * JDBC 2.0 Update a column with a String value. The updateXXX() methods
3326     * are used to update column values in the current row, or the insert row.
3327     * The updateXXX() methods do not update the underlying database, instead
3328     * the updateRow() or insertRow() methods are called to update the
3329     * database.
3330     *
3331     * @param columnIndex the first column is 1, the second is 2, ...
3332     * @param x the new column value
3333     *
3334     * @exception SQLException if a database-access error occurs
3335     * @throws NotUpdatable DOCUMENT ME!
3336     */

3337    public void updateString(int columnIndex, String JavaDoc x)
3338        throws SQLException JavaDoc {
3339        throw new NotUpdatable();
3340    }
3341
3342    /**
3343     * JDBC 2.0 Update a column with a String value. The updateXXX() methods
3344     * are used to update column values in the current row, or the insert row.
3345     * The updateXXX() methods do not update the underlying database, instead
3346     * the updateRow() or insertRow() methods are called to update the
3347     * database.
3348     *
3349     * @param columnName the name of the column
3350     * @param x the new column value
3351     *
3352     * @exception SQLException if a database-access error occurs
3353     */

3354    public void updateString(String JavaDoc columnName, String JavaDoc x)
3355        throws SQLException JavaDoc {
3356        updateString(findColumn(columnName), x);
3357    }
3358
3359    /**
3360     * JDBC 2.0 Update a column with a Time value. The updateXXX() methods are
3361     * used to update column values in the current row, or the insert row. The
3362     * updateXXX() methods do not update the underlying database, instead the
3363     * updateRow() or insertRow() methods are called to update the database.
3364     *
3365     * @param columnIndex the first column is 1, the second is 2, ...
3366     * @param x the new column value
3367     *
3368     * @exception SQLException if a database-access error occurs
3369     * @throws NotUpdatable DOCUMENT ME!
3370     */

3371    public void updateTime(int columnIndex, java.sql.Time JavaDoc x)
3372        throws SQLException JavaDoc {
3373        throw new NotUpdatable();
3374    }
3375
3376    /**
3377     * JDBC 2.0 Update a column with a Time value. The updateXXX() methods are
3378     * used to update column values in the current row, or the insert row. The
3379     * updateXXX() methods do not update the underlying database, instead the
3380     * updateRow() or insertRow() methods are called to update the database.
3381     *
3382     * @param columnName the name of the column
3383     * @param x the new column value
3384     *
3385     * @exception SQLException if a database-access error occurs
3386     */

3387    public void updateTime(String JavaDoc columnName, java.sql.Time JavaDoc x)
3388        throws SQLException JavaDoc {
3389        updateTime(findColumn(columnName), x);
3390    }
3391
3392    /**
3393     * JDBC 2.0 Update a column with a Timestamp value. The updateXXX() methods
3394     * are used to update column values in the current row, or the insert row.
3395     * The updateXXX() methods do not update the underlying database, instead
3396     * the updateRow() or insertRow() methods are called to update the
3397     * database.
3398     *
3399     * @param columnIndex the first column is 1, the second is 2, ...
3400     * @param x the new column value
3401     *
3402     * @exception SQLException if a database-access error occurs
3403     * @throws NotUpdatable DOCUMENT ME!
3404     */

3405    public void updateTimestamp(int columnIndex, java.sql.Timestamp JavaDoc x)
3406        throws SQLException JavaDoc {
3407        throw new NotUpdatable();
3408    }
3409
3410    /**
3411     * JDBC 2.0 Update a column with a Timestamp value. The updateXXX() methods
3412     * are used to update column values in the current row, or the insert row.
3413     * The updateXXX() methods do not update the underlying database, instead
3414     * the updateRow() or insertRow() methods are called to update the
3415     * database.
3416     *
3417     * @param columnName the name of the column
3418     * @param x the new column value
3419     *
3420     * @exception SQLException if a database-access error occurs
3421     */

3422    public void updateTimestamp(String JavaDoc columnName, java.sql.Timestamp JavaDoc x)
3423        throws SQLException JavaDoc {
3424        updateTimestamp(findColumn(columnName), x);
3425    }
3426
3427    /**
3428     * A column may have the value of SQL NULL; wasNull() reports whether the
3429     * last column read had this special value. Note that you must first call
3430     * getXXX on a column to try to read its value and then call wasNull() to
3431     * find if the value was SQL NULL
3432     *
3433     * @return true if the last column read was SQL NULL
3434     *
3435     * @exception java.sql.SQLException if a database access error occurred
3436     */

3437    public boolean wasNull() throws java.sql.SQLException JavaDoc {
3438        return wasNullFlag;
3439    }
3440
3441    ///////////////////////////////////////////
3442
//
3443
// These number conversion routines save
3444
// a ton of "new()s", especially for the heavily
3445
// used getInt() and getDouble() methods
3446
//
3447
///////////////////////////////////////////
3448

3449    /**
3450     * Converts a string representation of a number to a double. Need a faster
3451     * way to do this.
3452     *
3453     * @param colIndex the 1-based index of the column to retrieve a double
3454     * from.
3455     *
3456     * @return the double value represented by the string in buf
3457     *
3458     * @throws SQLException if an error occurs
3459     */

3460    protected double getDoubleInternal(int colIndex) throws SQLException JavaDoc {
3461        String JavaDoc s = "";
3462
3463        try {
3464            s = getString(colIndex);
3465
3466            if ((s == null) || (s.length() == 0)) {
3467                return 0;
3468            }
3469
3470            double d = Double.parseDouble(s);
3471
3472            if (this.useStrictFloatingPoint) {
3473                // Fix endpoint rounding precision loss in MySQL server
3474
if (d == 2.147483648E9) {
3475                    // Fix Odd end-point rounding on MySQL
3476
d = 2.147483647E9;
3477                } else if (d == 1.0000000036275E-15) {
3478                    // Fix odd end-point rounding on MySQL
3479
d = 1.0E-15;
3480                } else if (d == 9.999999869911E14) {
3481                    d = 9.99999999999999E14;
3482                } else if (d == 1.4012984643248E-45) {
3483                    d = 1.4E-45;
3484                } else if (d == 1.4013E-45) {
3485                    d = 1.4E-45;
3486                } else if (d == 3.4028234663853E37) {
3487                    d = 3.4028235E37;
3488                } else if (d == -2.14748E9) {
3489                    d = -2.147483648E9;
3490                } else if (d == 3.40282E37) {
3491                    d = 3.4028235E37;
3492                }
3493            }
3494
3495            return d;
3496        } catch (NumberFormatException JavaDoc e) {
3497            throw new SQLException JavaDoc("Bad format for number '" + s + "'");
3498        }
3499    }
3500
3501    /**
3502     * Sets the first character of the query that this result set was created
3503     * from.
3504     *
3505     * @param c the first character of the query...uppercased
3506     */

3507    protected void setFirstCharOfQuery(char c) {
3508        this.firstCharOfQuery = c;
3509    }
3510
3511    /**
3512     * Returns the first character of the query that this result set was
3513     * created from.
3514     *
3515     * @return the first character of the query...uppercased
3516     */

3517    protected char getFirstCharOfQuery() {
3518        return this.firstCharOfQuery;
3519    }
3520
3521    /**
3522     * Sets the concurrency (JDBC2)
3523     *
3524     * @param concurrencyFlag CONCUR_UPDATABLE or CONCUR_READONLY
3525     */

3526    protected void setResultSetConcurrency(int concurrencyFlag) {
3527        resultSetConcurrency = concurrencyFlag;
3528    }
3529
3530    /**
3531     * Sets the result set type for (JDBC2)
3532     *
3533     * @param typeFlag SCROLL_SENSITIVE or SCROLL_INSENSITIVE (we only support
3534     * SCROLL_INSENSITIVE)
3535     */

3536    protected void setResultSetType(int typeFlag) {
3537        resultSetType = typeFlag;
3538    }
3539
3540    /**
3541     * Sets server info (if any)
3542     *
3543     * @param info the server info message
3544     */

3545    protected void setServerInfo(String JavaDoc info) {
3546        this.serverInfo = info;
3547    }
3548
3549    /**
3550     * Returns the server info (if any), or null if none.
3551     *
3552     * @return server info created for this ResultSet
3553     */

3554    protected String JavaDoc getServerInfo() {
3555        return this.serverInfo;
3556    }
3557
3558    /**
3559     * Builds a hash between column names and their indices for fast retrieval.
3560     */

3561    protected void buildIndexMapping() {
3562        int numFields = fields.length;
3563        columnNameToIndex = new HashMap JavaDoc();
3564        fullColumnNameToIndex = new HashMap JavaDoc();
3565
3566        // We do this in reverse order, so that the 'first' column
3567
// with a given name ends up as the final mapping in the
3568
// hashtable...
3569
//
3570
// Quoting the JDBC Spec:
3571
//
3572
// "Column names used as input to getter
3573
// methods are case insensitive. When a getter method is called with a column
3574
// name and several columns have the same name, the value of the first
3575
// matching column will be returned. "
3576
//
3577

3578        for (int i = numFields-1; i>= 0 ; i--) {
3579            Integer JavaDoc index = new Integer JavaDoc(i);
3580            String JavaDoc columnName = fields[i].getName();
3581            String JavaDoc fullColumnName = fields[i].getFullName();
3582
3583            if (columnName != null) {
3584                columnNameToIndex.put(columnName, index);
3585                columnNameToIndex.put(columnName.toUpperCase(), index);
3586                columnNameToIndex.put(columnName.toLowerCase(), index);
3587            }
3588
3589            if (fullColumnName != null) {
3590                fullColumnNameToIndex.put(fullColumnName, index);
3591                fullColumnNameToIndex.put(fullColumnName.toUpperCase(), index);
3592                fullColumnNameToIndex.put(fullColumnName.toLowerCase(), index);
3593            }
3594        }
3595
3596        // set the flag to prevent rebuilding...
3597
hasBuiltIndexMapping = true;
3598    }
3599
3600    /**
3601     * Ensures that the result set is not closed
3602     *
3603     * @throws SQLException if the result set is closed
3604     */

3605    protected void checkClosed() throws SQLException JavaDoc {
3606        if (isClosed) {
3607            throw new SQLException JavaDoc("Operation not allowed after ResultSet closed",
3608                SQLError.SQL_STATE_GENERAL_ERROR);
3609        }
3610    }
3611
3612    /**
3613     * Ensures that the cursor is positioned on a valid row and that the result
3614     * set is not closed
3615     *
3616     * @throws SQLException if the result set is not in a valid state for
3617     * traversal
3618     */

3619    protected void checkRowPos() throws SQLException JavaDoc {
3620        checkClosed();
3621
3622        if (!rowData.isDynamic() && (rowData.size() == 0)) {
3623            throw new SQLException JavaDoc("Illegal operation on empty result set",
3624                SQLError.SQL_STATE_GENERAL_ERROR);
3625        }
3626
3627        if (rowData.isBeforeFirst()) {
3628            throw new SQLException JavaDoc("Before start of result set", SQLError.SQL_STATE_GENERAL_ERROR);
3629        }
3630
3631        if (rowData.isAfterLast()) {
3632            throw new SQLException JavaDoc("After end of result set", SQLError.SQL_STATE_GENERAL_ERROR);
3633        }
3634    }
3635
3636    protected void realClose(boolean closeRowData) throws SQLException JavaDoc {
3637        try {
3638            if (closeRowData && (this.rowData != null)) {
3639                rowData.close();
3640            }
3641        } finally {
3642            this.defaultTimeZone = null;
3643            this.rowData = null;
3644            this.isClosed = true;
3645        }
3646    }
3647
3648    void setStatement(com.mysql.jdbc.Statement stmt) {
3649        owningStatement = stmt;
3650    }
3651
3652    long getUpdateCount() {
3653        return updateCount;
3654    }
3655
3656    long getUpdateID() {
3657        return updateId;
3658    }
3659
3660    boolean reallyResult() {
3661        return reallyResult;
3662    }
3663
3664    /**
3665     * Get the value of a column in the current row as a java.sql.Time object
3666     * in the given timezone
3667     *
3668     * @param columnIndex the first column is 1, the second is 2...
3669     * @param tz the Timezone to use
3670     *
3671     * @return the column value; null if SQL NULL
3672     *
3673     * @exception java.sql.SQLException if a database access error occurs
3674     */

3675    private Time JavaDoc getTimeInternal(int columnIndex, TimeZone JavaDoc tz)
3676        throws java.sql.SQLException JavaDoc {
3677        int hr = 0;
3678        int min = 0;
3679        int sec = 0;
3680
3681        try {
3682            String JavaDoc timeAsString = getString(columnIndex);
3683
3684            if (timeAsString == null) {
3685                return null;
3686            } else {
3687                int length = timeAsString.length();
3688
3689                if ((length > 0) && (timeAsString.charAt(0) == '0')
3690                        && (timeAsString.equals("0000-00-00")
3691                        || timeAsString.equals("0000-00-00 00:00:00")
3692                        || timeAsString.equals("00000000000000"))) {
3693                    wasNullFlag = true;
3694
3695                    return null;
3696                }
3697
3698                Field timeColField = fields[columnIndex - 1];
3699
3700                if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_TIMESTAMP) {
3701                    // It's a timestamp
3702
switch (length) {
3703                    case 14:
3704                    case 12: {
3705                        hr = Integer.parseInt(timeAsString.substring(length - 6,
3706                                    length - 4));
3707                        min = Integer.parseInt(timeAsString.substring(length
3708                                    - 4, length - 2));
3709                        sec = Integer.parseInt(timeAsString.substring(length
3710                                    - 2, length));
3711                    }
3712
3713                    break;
3714
3715                    case 10: {
3716                        hr = Integer.parseInt(timeAsString.substring(6, 8));
3717                        min = Integer.parseInt(timeAsString.substring(8, 10));
3718                        sec = 0;
3719                    }
3720
3721                    break;
3722
3723                    default:
3724                        throw new SQLException JavaDoc(
3725                            "Timestamp too small to convert to Time value in column "
3726                            + columnIndex + "(" + fields[columnIndex - 1]
3727                            + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
3728                    } /* endswitch */
3729
3730                    SQLWarning JavaDoc precisionLost = new SQLWarning JavaDoc(
3731                            "Precision lost converting TIMESTAMP to Time with getTime() on column "
3732                            + columnIndex + "(" + fields[columnIndex - 1]
3733                            + ").");
3734
3735                    if (warningChain == null) {
3736                        warningChain = precisionLost;
3737                    } else {
3738                        warningChain.setNextWarning(precisionLost);
3739                    }
3740                } else if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_DATETIME) {
3741                    hr = Integer.parseInt(timeAsString.substring(11, 13));
3742                    min = Integer.parseInt(timeAsString.substring(14, 16));
3743                    sec = Integer.parseInt(timeAsString.substring(17, 19));
3744
3745                    SQLWarning JavaDoc precisionLost = new SQLWarning JavaDoc(
3746                            "Precision lost converting DATETIME to Time with getTime() on column "
3747                            + columnIndex + "(" + fields[columnIndex - 1]
3748                            + ").");
3749
3750                    if (warningChain == null) {
3751                        warningChain = precisionLost;
3752                    } else {
3753                        warningChain.setNextWarning(precisionLost);
3754                    }
3755                } else {
3756                    // convert a String to a Time
3757
if ((length != 5) && (length != 8)) {
3758                        throw new SQLException JavaDoc("Bad format for Time '"
3759                            + timeAsString + "' in column " + columnIndex + "("
3760                            + fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
3761                    }
3762
3763                    hr = Integer.parseInt(timeAsString.substring(0, 2));
3764                    min = Integer.parseInt(timeAsString.substring(3, 5));
3765                    sec = (length == 5) ? 0
3766                                        : Integer.parseInt(timeAsString
3767                            .substring(6));
3768                }
3769
3770                return TimeUtil.changeTimezone(this.connection,
3771                    fastTimeCreate(null, hr, min, sec),
3772                    connection.getServerTimezone(), tz);
3773            }
3774        } catch (Exception JavaDoc ex) {
3775            throw new java.sql.SQLException JavaDoc(ex.getClass().getName(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
3776        }
3777    }
3778
3779    /**
3780     * Get the value of a column in the current row as a java.sql.Timestamp
3781     * object in the given timezone
3782     *
3783     * @param columnIndex the first column is 1, the second is 2...
3784     * @param tz the timezone to use
3785     *
3786     * @return the column value; null if SQL NULL
3787     *
3788     * @exception java.sql.SQLException if a database access error occurs
3789     */

3790    private Timestamp JavaDoc getTimestampInternal(int columnIndex, TimeZone JavaDoc tz)
3791        throws java.sql.SQLException JavaDoc {
3792        String JavaDoc timestampValue = getString(columnIndex);
3793
3794        try {
3795            if (timestampValue == null) {
3796                return null;
3797            } else {
3798                int length = timestampValue.length();
3799
3800                if ((length > 0) && (timestampValue.charAt(0) == '0')
3801                        && (timestampValue.equals("0000-00-00")
3802                        || timestampValue.equals("0000-00-00 00:00:00")
3803                        || timestampValue.equals("00000000000000")
3804                        || timestampValue.equals("0"))) {
3805                    wasNullFlag = true;
3806
3807                    return null;
3808                } else if (fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {
3809                    return TimeUtil.changeTimezone(this.connection,
3810                        fastTimestampCreate(null,
3811                            Integer.parseInt(timestampValue.substring(0, 4))
3812                            - 1900, 0, 1, 0, 0, 0, 0),
3813                        connection.getServerTimezone(), tz);
3814                } else {
3815                    // Convert from TIMESTAMP or DATE
3816
switch (length) {
3817                    case 19: {
3818                        int year = Integer.parseInt(timestampValue.substring(
3819                                    0, 4));
3820                        int month = Integer.parseInt(timestampValue.substring(
3821                                    5, 7));
3822                        int day = Integer.parseInt(timestampValue.substring(8,
3823                                    10));
3824                        int hour = Integer.parseInt(timestampValue.substring(
3825                                    11, 13));
3826                        int minutes = Integer.parseInt(timestampValue.substring(
3827                                    14, 16));
3828                        int seconds = Integer.parseInt(timestampValue.substring(
3829                                    17, 19));
3830
3831                        return TimeUtil.changeTimezone(this.connection,
3832                            fastTimestampCreate(null, year - 1900, month - 1,
3833                                day, hour, minutes, seconds, 0),
3834                            connection.getServerTimezone(), tz);
3835                    }
3836
3837                    case 14: {
3838                        int year = Integer.parseInt(timestampValue.substring(
3839                                    0, 4));
3840                        int month = Integer.parseInt(timestampValue.substring(
3841                                    4, 6));
3842                        int day = Integer.parseInt(timestampValue.substring(6, 8));
3843                        int hour = Integer.parseInt(timestampValue.substring(
3844                                    8, 10));
3845                        int minutes = Integer.parseInt(timestampValue.substring(
3846                                    10, 12));
3847                        int seconds = Integer.parseInt(timestampValue.substring(
3848                                    12, 14));
3849
3850                        return TimeUtil.changeTimezone(this.connection,
3851                            fastTimestampCreate(null, year - 1900, month - 1,
3852                                day, hour, minutes, seconds, 0),
3853                            connection.getServerTimezone(), tz);
3854                    }
3855
3856                    case 12: {
3857                        int year = Integer.parseInt(timestampValue.substring(
3858                                    0, 2));
3859
3860                        if (year <= 69) {
3861                            year = (year + 100);
3862                        }
3863
3864                        int month = Integer.parseInt(timestampValue.substring(
3865                                    2, 4));
3866                        int day = Integer.parseInt(timestampValue.substring(4, 6));
3867                        int hour = Integer.parseInt(timestampValue.substring(
3868                                    6, 8));
3869                        int minutes = Integer.parseInt(timestampValue.substring(
3870                                    8, 10));
3871                        int seconds = Integer.parseInt(timestampValue.substring(
3872                                    10, 12));
3873
3874                        return TimeUtil.changeTimezone(this.connection,
3875                            fastTimestampCreate(null, year, month - 1, day,
3876                                hour, minutes, seconds, 0),
3877                            connection.getServerTimezone(), tz);
3878                    }
3879
3880                    case 10: {
3881                        int year;
3882                        int month;
3883                        int day;
3884                        int hour;
3885                        int minutes;
3886
3887                        if ((this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_DATE)
3888                                || (timestampValue.indexOf("-") != -1)) {
3889                            year = Integer.parseInt(timestampValue.substring(
3890                                        0, 4)) - 1900;
3891                            month = Integer.parseInt(timestampValue.substring(
3892                                        5, 7));
3893                            day = Integer.parseInt(timestampValue.substring(8,
3894                                        10));
3895                            hour = 0;
3896                            minutes = 0;
3897                        } else {
3898                            year = Integer.parseInt(timestampValue.substring(
3899                                        0, 2));
3900
3901                            if (year <= 69) {
3902                                year = (year + 100);
3903                            }
3904
3905                            month = Integer.parseInt(timestampValue.substring(
3906                                        2, 4));
3907                            day = Integer.parseInt(timestampValue.substring(4, 6));
3908                            hour = Integer.parseInt(timestampValue.substring(
3909                                        6, 8));
3910                            minutes = Integer.parseInt(timestampValue.substring(
3911                                        8, 10));
3912                        }
3913
3914                        return TimeUtil.changeTimezone(this.connection,
3915                            fastTimestampCreate(null, year, month - 1, day,
3916                                hour, minutes, 0, 0),
3917                            connection.getServerTimezone(), tz);
3918                    }
3919
3920                    case 8: {
3921                        int year = Integer.parseInt(timestampValue.substring(
3922                                    0, 4));
3923                        int month = Integer.parseInt(timestampValue.substring(
3924                                    4, 6));
3925                        int day = Integer.parseInt(timestampValue.substring(6, 8));
3926
3927                        return TimeUtil.changeTimezone(this.connection,
3928                            fastTimestampCreate(null, year - 1900, month - 1,
3929                                day, 0, 0, 0, 0),
3930                            connection.getServerTimezone(), tz);
3931                    }
3932
3933                    case 6: {
3934                        int year = Integer.parseInt(timestampValue.substring(
3935                                    0, 2));
3936
3937                        if (year <= 69) {
3938                            year = (year + 100);
3939                        }
3940
3941                        int month = Integer.parseInt(timestampValue.substring(
3942                                    2, 4));
3943                        int day = Integer.parseInt(timestampValue.substring(4, 6));
3944
3945                        return TimeUtil.changeTimezone(this.connection,
3946                            fastTimestampCreate(null, year, month - 1, day, 0,
3947                                0, 0, 0), connection.getServerTimezone(), tz);
3948                    }
3949
3950                    case 4: {
3951                        int year = Integer.parseInt(timestampValue.substring(
3952                                    0, 2));
3953
3954                        if (year <= 69) {
3955                            year = (year + 100);
3956                        }
3957
3958                        int month = Integer.parseInt(timestampValue.substring(
3959                                    2, 4));
3960
3961                        return TimeUtil.changeTimezone(this.connection,
3962                            fastTimestampCreate(null, year, month - 1, 1, 0, 0,
3963                                0, 0), connection.getServerTimezone(), tz);
3964                    }
3965
3966                    case 2: {
3967                        int year = Integer.parseInt(timestampValue.substring(
3968                                    0, 2));
3969
3970                        if (year <= 69) {
3971                            year = (year + 100);
3972                        }
3973
3974                        return TimeUtil.changeTimezone(this.connection,
3975                            fastTimestampCreate(null, year, 0, 1, 0, 0, 0, 0),
3976                            connection.getServerTimezone(), tz);
3977                    }
3978
3979                    default:
3980                        throw new java.sql.SQLException JavaDoc(
3981                            "Bad format for Timestamp '" + timestampValue
3982                            + "' in column " + columnIndex + "("
3983                            + fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
3984                    }
3985                }
3986            }
3987        } catch (Exception JavaDoc e) {
3988            throw new java.sql.SQLException JavaDoc("Cannot convert value '"
3989                + timestampValue + "' from column " + columnIndex + "("
3990                + timestampValue + " ) to TIMESTAMP.", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
3991        }
3992    }
3993
3994    private synchronized Date JavaDoc fastDateCreate(Calendar JavaDoc cal, int year, int month,
3995        int day) {
3996        if (cal == null) {
3997            if (this.fastDateCal == null) {
3998                this.fastDateCal = new GregorianCalendar JavaDoc();
3999
4000                this.fastDateCal.setTimeZone(this.defaultTimeZone);
4001            }
4002
4003            cal = this.fastDateCal;
4004        }
4005
4006        cal.clear();
4007        cal.set(year + 1900, month, day, 0, 0, 0);
4008
4009        long dateAsMillis = 0;
4010
4011        try {
4012            dateAsMillis = cal.getTimeInMillis();
4013        } catch (IllegalAccessError JavaDoc iae) {
4014            // Must be on JDK-1.3.1 or older....
4015
dateAsMillis = cal.getTime().getTime();
4016        }
4017
4018        return new Date JavaDoc(dateAsMillis);
4019    }
4020
4021    private synchronized Time JavaDoc fastTimeCreate(Calendar JavaDoc cal, int hour,
4022        int minute, int second) {
4023        if (cal == null) {
4024            if (this.fastDateCal == null) {
4025                this.fastDateCal = new GregorianCalendar JavaDoc();
4026
4027                this.fastDateCal.setTimeZone(this.defaultTimeZone);
4028            }
4029
4030            cal = this.fastDateCal;
4031        }
4032
4033        cal.clear();
4034
4035        // Set 'date' to epoch of Jan 1, 1970
4036
cal.set(1970, 0, 1, hour, minute, second);
4037
4038        long timeAsMillis = 0;
4039
4040        try {
4041            timeAsMillis = cal.getTimeInMillis();
4042        } catch (IllegalAccessError JavaDoc iae) {
4043            // Must be on JDK-1.3.1 or older....
4044
timeAsMillis = cal.getTime().getTime();
4045        }
4046
4047        return new Time JavaDoc(timeAsMillis);
4048    }
4049
4050    private synchronized Timestamp JavaDoc fastTimestampCreate(Calendar JavaDoc cal, int year,
4051        int month, int day, int hour, int minute, int seconds, int secondsPart) {
4052        if (cal == null) {
4053            if (this.fastDateCal == null) {
4054                this.fastDateCal = new GregorianCalendar JavaDoc();
4055
4056                this.fastDateCal.setTimeZone(this.defaultTimeZone);
4057            }
4058
4059            cal = this.fastDateCal;
4060        }
4061
4062        cal.clear();
4063        cal.set(year + 1900, month, day, hour, minute, seconds);
4064
4065        long tsAsMillis = 0;
4066
4067        try {
4068            tsAsMillis = cal.getTimeInMillis();
4069        } catch (IllegalAccessError JavaDoc iae) {
4070            // Must be on JDK-1.3.1 or older....
4071
tsAsMillis = cal.getTime().getTime();
4072        }
4073
4074        Timestamp JavaDoc ts = new Timestamp JavaDoc(tsAsMillis);
4075        ts.setNanos(secondsPart);
4076
4077        return ts;
4078    }
4079}
4080
Popular Tags