KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mckoi > database > jdbc > MResultSet


1 /**
2  * com.mckoi.database.jdbc.MResultSet 19 Jul 2000
3  *
4  * Mckoi SQL Database ( http://www.mckoi.com/database )
5  * Copyright (C) 2000, 2001, 2002 Diehl and Associates, Inc.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * Version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License Version 2 for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * Version 2 along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  *
20  * Change Log:
21  *
22  *
23  */

24
25 package com.mckoi.database.jdbc;
26
27 import java.io.*;
28 import java.sql.*;
29 import java.math.BigDecimal JavaDoc;
30 import java.util.Calendar JavaDoc;
31 import java.util.Hashtable JavaDoc;
32 import java.util.Vector JavaDoc;
33 import com.mckoi.database.global.ColumnDescription;
34 import com.mckoi.database.global.ByteLongObject;
35 import com.mckoi.database.global.ObjectTransfer;
36 import com.mckoi.database.global.StreamableObject;
37 import com.mckoi.database.global.ObjectTranslator;
38 import com.mckoi.database.global.SQLTypes;
39 import com.mckoi.database.global.StringObject;
40 import com.mckoi.util.BigNumber;
41
42 /**
43  * Implementation of a ResultSet.
44  * <p>
45  * Multi-threaded issue: This class is not designed to be multi-thread
46  * safe. A ResultSet should not be accessed by concurrent threads.
47  *
48  * @author Tobias Downer
49  */

50
51 public final class MResultSet implements ResultSet {
52
53   /**
54    * The default fetch size.
55    */

56   private static final int DEFAULT_FETCH_SIZE = 32;
57
58   /**
59    * The maximum fetch size.
60    */

61   private static final int MAXIMUM_FETCH_SIZE = 512;
62
63   /**
64    * The current unique id key.
65    */

66   private static int unique_id_key = 1;
67
68   /**
69    * BigNumber for 0.
70    */

71   private static BigNumber BD_ZERO = BigNumber.fromInt(0);
72
73
74   /**
75    * A unique int that refers to this result set.
76    */

77   private int unique_id;
78
79   /**
80    * The MConnection that this result set is in.
81    */

82   private MConnection connection;
83
84   /**
85    * The MStatement that this result is from.
86    */

87   private MStatement statement;
88
89   /**
90    * SQL warnings for this result set. Cleared each time a new row accessed.
91    */

92   private SQLWarning head_warning;
93
94   /**
95    * The current result_id for the information in the current result set.
96    */

97   private int result_id;
98
99   /**
100    * The array of ColumnDescription that describes each column in the result
101    * set.
102    */

103   private ColumnDescription[] col_list;
104
105   /**
106    * The length of time it took to execute this query in ms.
107    */

108   private int query_time_ms;
109
110   /**
111    * The number of rows in the result set.
112    */

113   private int result_row_count;
114
115   /**
116    * The maximum row count as set in the Statement by the 'setMaxRows' method
117    * or 0 if the max row count is not important.
118    */

119   private int max_row_count = Integer.MAX_VALUE;
120
121   /**
122    * The row number of the first row of the 'result_block'
123    */

124   private int block_top_row;
125
126   /**
127    * The number of rows in 'result_block'
128    */

129   private int block_row_count;
130
131   /**
132    * The number of rows to fetch each time we need to get rows from the
133    * database.
134    */

135   private int fetch_size;
136
137   /**
138    * The Vector that contains the Objects downloaded into this result set.
139    * It only contains the objects from the last block of rows downloaded.
140    */

141   private Vector JavaDoc result_block;
142
143   /**
144    * The real index of the result set we are currently at.
145    */

146   private int real_index = Integer.MAX_VALUE;
147
148   /**
149    * The offset into 'result_block' where 'real_index' is. This is set up
150    * by 'ensureIndexLoaded'.
151    */

152   private int real_index_offset = -1;
153
154   /**
155    * Set to true if the last 'getxxx' method was a null. Otherwise set to
156    * false.
157    */

158   private boolean last_was_null = false;
159
160   /**
161    * A Hashtable that acts as a cache for column name/column number look ups.
162    */

163   private Hashtable JavaDoc column_hash;
164
165   /**
166    * Set to true if the result set is closed on the server.
167    */

168   private boolean closed_on_server;
169
170
171
172
173
174   /**
175    * Constructor.
176    */

177   MResultSet(MConnection connection, MStatement statement) {
178     this.connection = connection;
179     this.statement = statement;
180     unique_id = unique_id_key++;
181     result_id = -1;
182     result_block = new Vector JavaDoc();
183   }
184
185
186
187   /**
188    * Adds a new SQLWarning to the chain.
189    */

190   void addSQLWarning(SQLWarning warning) {
191     if (head_warning == null) {
192       head_warning = warning;
193     }
194     else {
195       head_warning.setNextWarning(warning);
196     }
197   }
198
199   /**
200    * Returns true if verbose column names are enabled on the connection.
201    * Returns false by default.
202    */

203   boolean verboseColumnNames() {
204     return connection.verboseColumnNames();
205   }
206
207   // ---------- Connection callback methods ----------
208
// These methods are called back from the ConnectionThread running on the
209
// connection. These methods require some synchronization thought.
210

211   /**
212    * Called by the ConnectionThread when we have received the initial bag of
213    * the result set. This contains information about the columns in the
214    * result, the number of rows in the entire set, etc. This sets up the
215    * result set to handle the result.
216    */

217   void connSetup(int result_id, ColumnDescription[] col_list,
218                  int total_row_count) {
219     this.result_id = result_id;
220     this.col_list = col_list;
221     this.result_row_count = total_row_count;
222     block_top_row = -1;
223     result_block.removeAllElements();
224
225     real_index = -1;
226     fetch_size = DEFAULT_FETCH_SIZE;
227     closed_on_server = false;
228   }
229
230   /**
231    * Sets the length of time in milliseconds (server-side) it took to execute
232    * this query. Useful as feedback for the server-side optimisation systems.
233    * <p>
234    * VERY MINOR ISSUE: An int can 'only' contain 35 weeks worth of
235    * milliseconds. So if a query takes longer than that this number will
236    * overflow.
237    */

238   void setQueryTime(int time_ms) {
239     query_time_ms = time_ms;
240   }
241
242   /**
243    * Sets the maximum number of rows that this ResultSet will return or 0 if
244    * the max number of rows is not important. This is set by MStatement
245    * when a query is evaluated.
246    */

247   void setMaxRowCount(int row_count) {
248     if (row_count == 0) {
249       max_row_count = Integer.MAX_VALUE;
250     }
251     else {
252       max_row_count = row_count;
253     }
254   }
255
256   /**
257    * Returns true if this ResultSet contains large objects. This looks at the
258    * ColumnDescription object to determine this.
259    */

260   boolean containsLargeObjects() {
261     for (int i = 0; i < col_list.length; ++i) {
262       ColumnDescription col = col_list[i];
263       int sql_type = col.getSQLType();
264       if (sql_type == com.mckoi.database.global.SQLTypes.BINARY ||
265           sql_type == com.mckoi.database.global.SQLTypes.VARBINARY ||
266           sql_type == com.mckoi.database.global.SQLTypes.LONGVARBINARY ||
267           sql_type == com.mckoi.database.global.SQLTypes.BLOB ||
268           sql_type == com.mckoi.database.global.SQLTypes.CHAR ||
269           sql_type == com.mckoi.database.global.SQLTypes.VARCHAR ||
270           sql_type == com.mckoi.database.global.SQLTypes.LONGVARCHAR ||
271           sql_type == com.mckoi.database.global.SQLTypes.CLOB) {
272         return true;
273       }
274     }
275     return false;
276   }
277   
278   /**
279    * Asks the server for all the rows in the result set and stores it
280    * locally within this object. It then disposes all resources associated
281    * with this result set on the server.
282    */

283   void storeResultLocally() throws SQLException {
284     // After this call, 'result_block' will contain the whole result set.
285
updateResultPart(0, rowCount());
286     // Request to close the current result set on the server.
287
connection.disposeResult(result_id);
288     closed_on_server = true;
289   }
290
291   /**
292    * Asks the server for more information about this result set to put
293    * into the 'result_block'. This should be called when we need to request
294    * more information from the server.
295    * <p>
296    * @param row_index the top row index from the block of the result set to
297    * download.
298    * @param row_count the maximum number of rows to download (may be less if
299    * no more are available).
300    */

301   void updateResultPart(int row_index, int row_count) throws SQLException {
302
303     // If row_count is 0 then we don't need to do anything.
304
if (row_count == 0) {
305       return;
306     }
307
308     if (row_index + row_count < 0) {
309       throw new SQLException(
310                         "ResultSet row index is before the start of the set.");
311     }
312     else if (row_index < 0) {
313       row_index = 0;
314       row_count = row_count + row_index;
315     }
316
317     if (row_index >= rowCount()) {
318       throw new SQLException(
319                            "ResultSet row index is after the end of the set.");
320     }
321     else if (row_index + row_count > rowCount()) {
322       row_count = rowCount() - row_index;
323     }
324
325     if (result_id == -1) {
326       throw new SQLException("result_id == -1. No result to get from.");
327     }
328
329     try {
330
331       // Request the result via the RowCache. If the information is not found
332
// in the row cache then the request is forwarded onto the database.
333
result_block = connection.getRowCache().getResultPart(result_block,
334                   connection, result_id, row_index, row_count,
335                   columnCount(), rowCount());
336
337       // Set the row that's at the top
338
block_top_row = row_index;
339       // Set the number of rows in the block.
340
block_row_count = row_count;
341
342 // // Request a part of a result from the server (blocks)
343
// DataInputStream din = connection.requestResultPart(result_id,
344
// row_index, row_count);
345
//
346
// // Clear the block.
347
// result_block.removeAllElements();
348
// int num_entries = row_count * columnCount();
349
// for (int i = 0; i < num_entries; ++i) {
350
// result_block.addElement(ObjectTransfer.readFrom(din));
351
// }
352

353     }
354     catch (IOException e) {
355       e.printStackTrace();
356       throw new SQLException("IO Error: " + e.getMessage());
357     }
358
359   }
360
361   /**
362    * Closes the current server side result for this result set ready for a
363    * new one. This should be called before we execute a query. It sends a
364    * command to the server to despose of any resources associated with the
365    * current result_id.
366    * <p>
367    * It's perfectly safe to call this method even if we haven't downloaded
368    * a result set from the server and you may also safely call it multiple
369    * times (it will only send one request to the server).
370    */

371   void closeCurrentResult() throws SQLException {
372     if (getResultID() != -1) {
373       if (!closed_on_server) {
374         // Request to close the current result set
375
connection.disposeResult(result_id);
376         closed_on_server = true;
377       }
378       result_id = -1;
379       real_index = Integer.MAX_VALUE;
380       // Clear the column name -> index mapping,
381
if (column_hash != null) {
382         column_hash.clear();
383       }
384     }
385   }
386
387   /**
388    * Returns the 'result_id' that is used as a key to refer to the result set
389    * on the server that is the result of the query. A 'resultID' of -1 means
390    * there is no server side result set associated with this object.
391    */

392   int getResultID() {
393     return result_id;
394   }
395
396   /**
397    * The total number of rows in the result set.
398    */

399   int rowCount() {
400     // The row count is whatever is the least between max_row_count (the
401
// maximum the user has set) and result_row_count (the actual number of
402
// rows in the result.
403
return Math.min(result_row_count, max_row_count);
404   }
405
406   /**
407    * The column count of columns in the result set.
408    */

409   int columnCount() {
410     return col_list.length;
411   }
412
413   /**
414    * Returns the ColumnDescription of the given column (first column is 0,
415    * etc).
416    */

417   ColumnDescription getColumn(int column) {
418     return col_list[column];
419   }
420
421   /**
422    * Returns true if this result set contains 1 column and 1 row and the name
423    * of the column is 'result'. This indicates the result set is a DDL
424    * command ( UPDATE, INSERT, CREATE, ALTER, etc ).
425    * <p>
426    * <strong>NOTE:</strong> This is a minor hack because there is no real
427    * indication that this is a DML statement. Theoretically a DQL query could
428    * be constructed that meets all these requirements and is processed
429    * incorrectly.
430    */

431   boolean isUpdate() {
432     // Must have 1 col and 1 row and the title of the column must be
433
// 'result' aliased.
434
return (columnCount() == 1 && rowCount() == 1 &&
435             getColumn(0).getName().equals("@aresult"));
436   }
437
438   /**
439    * Returns this ResultSet as an 'int' value. This is only valid if the
440    * result set has a single column and a single row of type 'BigNumber'.
441    */

442   int intValue() throws SQLException {
443     if (isUpdate()) {
444       Object JavaDoc ob = result_block.elementAt(0);
445       if (ob instanceof BigNumber) {
446         return ((BigNumber) ob).intValue();
447       }
448       else {
449         return 0;
450       }
451     }
452     throw new SQLException("Unable to format query result as an update value.");
453   }
454
455   /**
456    * Disposes of all resources associated with this result set. This could
457    * either be called from the MStatement finalize or close method. Calls to
458    * this object are undefined after this method has finished.
459    */

460   void dispose() {
461     try {
462       close();
463     }
464     catch (SQLException e) {
465       // Ignore
466
// We ignore exceptions because handling cases where the server
467
// connection has broken for many ResultSets would be annoying.
468
}
469
470     connection = null;
471     statement = null;
472     col_list = null;
473     result_block = null;
474   }
475
476   /**
477    * Ensures that the row index pointed to by 'real_index' is actually loaded
478    * into the 'result_block'. If not, we send a request to the database to
479    * get it.
480    */

481   void ensureIndexLoaded() throws SQLException {
482     if (real_index == -1) {
483       throw new SQLException("Row index out of bounds.");
484     }
485
486     // Offset into our block
487
int row_offset = real_index - block_top_row;
488     if (row_offset >= block_row_count) {
489       // Need to download the next block from the server.
490
updateResultPart(real_index, fetch_size);
491       // Set up the index into the downloaded block.
492
row_offset = real_index - block_top_row;
493       real_index_offset = row_offset * columnCount();
494     }
495     else if (row_offset < 0) {
496       int fs_dif = Math.min(fetch_size, 8);
497       // Need to download the next block from the server.
498
updateResultPart(real_index - fetch_size + fs_dif, fetch_size);
499       // Set up the index into the downloaded block.
500
row_offset = real_index - block_top_row;
501       real_index_offset = row_offset * columnCount();
502     }
503   }
504
505   /**
506    * Searches for the index of the column with the given name. First column
507    * index is 1, second is 2, etc.
508    */

509   int findColumnIndex(String JavaDoc name) throws SQLException {
510     // For speed, we keep column name -> column index mapping in the hashtable.
511
// This makes column reference by string faster.
512
if (column_hash == null) {
513       column_hash = new Hashtable JavaDoc();
514     }
515
516     boolean case_insensitive = connection.isCaseInsensitiveIdentifiers();
517     if (case_insensitive) {
518       name = name.toUpperCase();
519     }
520
521     Integer JavaDoc index = (Integer JavaDoc) column_hash.get(name);
522     if (index == null) {
523       int col_count = columnCount();
524       // First construct an unquoted list of all column names
525
String JavaDoc[] cols = new String JavaDoc[col_count];
526       for (int i = 0; i < col_count; ++i) {
527         String JavaDoc col_name = col_list[i].getName();
528         if (col_name.startsWith("\"")) {
529           col_name = col_name.substring(1, col_name.length() - 1);
530         }
531         // Strip any codes from the name
532
if (col_name.startsWith("@")) {
533           col_name = col_name.substring(2);
534         }
535         if (case_insensitive) {
536           col_name = col_name.toUpperCase();
537         }
538         cols[i] = col_name;
539       }
540
541       for (int i = 0; i < col_count; ++i) {
542         String JavaDoc col_name = cols[i];
543         if (col_name.equals(name)) {
544           column_hash.put(name, new Integer JavaDoc(i + 1));
545           return i + 1;
546         }
547       }
548
549       // If not found then search for column name ending,
550
String JavaDoc point_name = "." + name;
551       for (int i = 0; i < col_count; ++i) {
552         String JavaDoc col_name = cols[i];
553         if (col_name.endsWith(point_name)) {
554           column_hash.put(name, new Integer JavaDoc(i + 1));
555           return i + 1;
556         }
557       }
558
559 // // DEBUG: output the list of columns,
560
// for (int i = 0; i < col_count; ++i) {
561
// System.out.println(cols[i]);
562
// }
563
throw new SQLException("Couldn't find column with name: " + name);
564     }
565     else {
566       return index.intValue();
567     }
568   }
569
570   /**
571    * Returns the column Object of the current index. The first column is 1,
572    * the second is 2, etc.
573    */

574   Object JavaDoc getRawColumn(int column) throws SQLException {
575     // ASSERTION -
576
// Is the given column in bounds?
577
if (column < 1 || column > columnCount()) {
578       throw new SQLException(
579           "Column index out of bounds: 1 > " + column + " > " + columnCount());
580     }
581     // Ensure the current indexed row is fetched from the server.
582
ensureIndexLoaded();
583     // Return the raw cell object.
584
Object JavaDoc ob = result_block.elementAt(real_index_offset + (column - 1));
585     // Null check of the returned object,
586
if (ob != null) {
587       last_was_null = false;
588       // If this is a java object then deserialize it,
589
// ISSUE: Cache deserialized objects?
590
if (getColumn(column - 1).getSQLType() ==
591                              com.mckoi.database.global.SQLTypes.JAVA_OBJECT) {
592         ob = ObjectTranslator.deserialize((ByteLongObject) ob);
593       }
594       return ob;
595     }
596     last_was_null = true;
597     return null;
598   }
599
600   /**
601    * Returns the column Object of the name of the current index.
602    */

603   Object JavaDoc getRawColumn(String JavaDoc name) throws SQLException {
604     return getRawColumn(findColumnIndex(name));
605   }
606
607   /**
608    * This should be called when the 'real_index' variable changes. It updates
609    * internal variables.
610    */

611   private void realIndexUpdate() throws SQLException {
612     // Set up the index into the downloaded block.
613
int row_offset = real_index - block_top_row;
614     real_index_offset = row_offset * columnCount();
615     // Clear any warnings as in the spec.
616
clearWarnings();
617   }
618
619   /**
620    * Returns true if the given object is either an instanceof StringObject or
621    * is an instanceof StreamableObject, and therefore can be made into a
622    * string.
623    */

624   private boolean canMakeString(Object JavaDoc ob) {
625     return (ob instanceof StringObject || ob instanceof StreamableObject);
626   }
627   
628   /**
629    * If the object represents a String or is a form that can be readily
630    * translated to a String (such as a Clob, String, BigNumber, Boolean, etc)
631    * the string representation of the given Object is returned. This method is
632    * a convenient way to convert objects such as Clobs into java.util.String
633    * objects. This will cause a ClassCastException if the given object
634    * represents a BLOB or ByteLongObject.
635    */

636   private String JavaDoc makeString(Object JavaDoc ob) throws SQLException {
637     if (ob instanceof StreamableObject) {
638       Clob clob = asClob(ob);
639       long clob_len = clob.length();
640       if (clob_len < 16384L * 65536L) {
641         return clob.getSubString(1, (int) clob_len);
642       }
643       throw new SQLException("Clob too large to return as a string.");
644     }
645     else if (ob instanceof ByteLongObject) {
646       throw new ClassCastException JavaDoc();
647     }
648     else {
649       return ob.toString();
650     }
651   }
652
653   /**
654    * Returns the given object as a Blob instance.
655    */

656   private Blob asBlob(Object JavaDoc ob) {
657     if (ob instanceof StreamableObject) {
658       StreamableObject s_ob = (StreamableObject) ob;
659       byte type = (byte) (s_ob.getType() & 0x0F);
660       if (type == 2) {
661         return new MStreamableBlob(connection, result_id, type,
662                                    s_ob.getIdentifier(), s_ob.getSize());
663       }
664     }
665     else if (ob instanceof ByteLongObject) {
666       return new MBlob((ByteLongObject) ob);
667     }
668     throw new ClassCastException JavaDoc();
669   }
670
671   /**
672    * Returns the given object as a Clob instance.
673    */

674   private Clob asClob(Object JavaDoc ob) {
675     if (ob instanceof StreamableObject) {
676       StreamableObject s_ob = (StreamableObject) ob;
677       byte type = (byte) (s_ob.getType() & 0x0F);
678       if (type == 3 ||
679           type == 4) {
680         return new MStreamableClob(connection, result_id, type,
681                                    s_ob.getIdentifier(), s_ob.getSize());
682       }
683     }
684     else if (ob instanceof StringObject) {
685       return new MClob(ob.toString());
686     }
687     throw new ClassCastException JavaDoc();
688   }
689   
690   /**
691    * Casts an internal object to the sql_type given for return by methods
692    * such as 'getObject'.
693    */

694   private Object JavaDoc jdbcObjectCast(Object JavaDoc ob, int sql_type) throws SQLException {
695     switch (sql_type) {
696       case(SQLTypes.BIT):
697         return ob;
698       case(SQLTypes.TINYINT):
699         return new Byte JavaDoc(((BigNumber) ob).byteValue());
700       case(SQLTypes.SMALLINT):
701         return new Short JavaDoc(((BigNumber) ob).shortValue());
702       case(SQLTypes.INTEGER):
703         return new Integer JavaDoc(((BigNumber) ob).intValue());
704       case(SQLTypes.BIGINT):
705         return new Long JavaDoc(((BigNumber) ob).longValue());
706       case(SQLTypes.FLOAT):
707         return new Double JavaDoc(((BigNumber) ob).doubleValue());
708       case(SQLTypes.REAL):
709         return new Float JavaDoc(((BigNumber) ob).floatValue());
710       case(SQLTypes.DOUBLE):
711         return new Double JavaDoc(((BigNumber) ob).doubleValue());
712       case(SQLTypes.NUMERIC):
713         return ((BigNumber) ob).asBigDecimal();
714       case(SQLTypes.DECIMAL):
715         return ((BigNumber) ob).asBigDecimal();
716       case(SQLTypes.CHAR):
717         return makeString(ob);
718       case(SQLTypes.VARCHAR):
719         return makeString(ob);
720       case(SQLTypes.LONGVARCHAR):
721         return makeString(ob);
722       case(SQLTypes.DATE):
723         return new java.sql.Date JavaDoc(((java.util.Date JavaDoc) ob).getTime());
724       case(SQLTypes.TIME):
725         return new java.sql.Time JavaDoc(((java.util.Date JavaDoc) ob).getTime());
726       case(SQLTypes.TIMESTAMP):
727         return new java.sql.Timestamp JavaDoc(((java.util.Date JavaDoc) ob).getTime());
728       case(SQLTypes.BINARY):
729         // fall through
730
case(SQLTypes.VARBINARY):
731         // fall through
732
case(SQLTypes.LONGVARBINARY):
733         Blob b = asBlob(ob);
734         return b.getBytes(1, (int) b.length());
735       case(SQLTypes.NULL):
736         return ob;
737       case(SQLTypes.OTHER):
738         return ob;
739       case(SQLTypes.JAVA_OBJECT):
740         return ob;
741       case(SQLTypes.DISTINCT):
742         // (Not supported)
743
return ob;
744       case(SQLTypes.STRUCT):
745         // (Not supported)
746
return ob;
747       case(SQLTypes.ARRAY):
748         // (Not supported)
749
return ob;
750 //#IFDEF(JDBC2.0)
751
case(SQLTypes.BLOB):
752         return asBlob(ob);
753       case(SQLTypes.CLOB):
754         return asClob(ob);
755       case(SQLTypes.REF):
756         // (Not supported)
757
return ob;
758 //#ENDIF
759
default:
760         return ob;
761     }
762   }
763
764   // ---------- JDBC Extentions ----------
765
// All non-standard extentions to the JDBC API. This is rather ugly because
766
// to use these we need to cast to a com.mckoi.database.jdbc.? class.
767

768   /**
769    * The number of milliseconds it took the server to execute this query.
770    * This is set after the call to 'connSetup' so is available as soon as the
771    * header information is received from the server.
772    */

773   public int extQueryTimeMillis() {
774     return query_time_ms;
775   }
776
777   /**
778    * Access column as java.util.Date (which is the native object used in the
779    * mckoi database to handle time).
780    */

781   public java.util.Date JavaDoc extGetDate(int columnIndex) throws SQLException {
782     return (java.util.Date JavaDoc) getRawColumn(columnIndex);
783   }
784
785   /**
786    * Access column as java.util.Date (which is the native object used in the
787    * mckoi database to handle time).
788    */

789   public java.util.Date JavaDoc extGetDate(String JavaDoc columnName) throws SQLException {
790     return extGetDate(findColumnIndex(columnName));
791   }
792
793   // ---------- Implemented from ResultSet ----------
794

795   public boolean next() throws SQLException {
796     int row_count = rowCount();
797     if (real_index < row_count) {
798       ++real_index;
799       if (real_index < row_count) {
800         realIndexUpdate();
801       }
802     }
803     return (real_index < row_count);
804   }
805
806   public void close() throws SQLException {
807     closeCurrentResult();
808   }
809
810   public boolean wasNull() throws SQLException {
811     // Note: we don't check that a previous value was read.
812
return last_was_null;
813   }
814
815   //======================================================================
816
// Methods for accessing results by column index
817
//======================================================================
818

819   public String JavaDoc getString(int columnIndex) throws SQLException {
820     Object JavaDoc str = getRawColumn(columnIndex);
821     if (str == null) {
822       return null;
823     }
824     else {
825       if (canMakeString(str)) {
826         return makeString(str);
827       }
828       else {
829         // For date, time and timestamp we must format as per the JDBC
830
// specification.
831
if (str instanceof java.util.Date JavaDoc) {
832           int sql_type = getColumn(columnIndex - 1).getSQLType();
833           return jdbcObjectCast(str, sql_type).toString();
834         }
835         return str.toString();
836       }
837     }
838   }
839
840   public boolean getBoolean(int columnIndex) throws SQLException {
841     Object JavaDoc ob = getRawColumn(columnIndex);
842     if (ob == null) {
843       return false;
844     }
845     else if (ob instanceof Boolean JavaDoc) {
846       return ((Boolean JavaDoc) ob).booleanValue();
847     }
848     else if (ob instanceof BigNumber) {
849       return ((BigNumber) ob).compareTo(BD_ZERO) != 0;
850     }
851     else if (canMakeString(ob)) {
852       return makeString(ob).equalsIgnoreCase("true");
853     }
854     else {
855       throw new SQLException("Unable to cast value in ResultSet to boolean");
856     }
857   }
858
859   public byte getByte(int columnIndex) throws SQLException {
860     // Translates from BigNumber
861
BigNumber num = getBigNumber(columnIndex);
862     return num == null ? 0 : num.byteValue();
863   }
864
865   public short getShort(int columnIndex) throws SQLException {
866     // Translates from BigNumber
867
BigNumber num = getBigNumber(columnIndex);
868     return num == null ? 0 : num.shortValue();
869   }
870
871   public int getInt(int columnIndex) throws SQLException {
872     // Translates from BigNumber
873
BigNumber num = getBigNumber(columnIndex);
874     return num == null ? 0 : num.intValue();
875   }
876
877   public long getLong(int columnIndex) throws SQLException {
878     // Translates from BigNumber
879
BigNumber num = getBigNumber(columnIndex);
880     return num == null ? 0 : num.longValue();
881   }
882
883   public float getFloat(int columnIndex) throws SQLException {
884     // Translates from BigNumber
885
BigNumber num = getBigNumber(columnIndex);
886     return num == null ? 0 : num.floatValue();
887   }
888
889   public double getDouble(int columnIndex) throws SQLException {
890     // Translates from BigNumber
891
BigNumber num = getBigNumber(columnIndex);
892     return num == null ? 0 : num.doubleValue();
893   }
894
895   /**
896    * @deprecated
897    */

898   public BigDecimal JavaDoc getBigDecimal(int columnIndex, int scale)
899                                                       throws SQLException {
900     return getBigDecimal(columnIndex);
901   }
902
903   public byte[] getBytes(int columnIndex) throws SQLException {
904     Blob b = getBlob(columnIndex);
905     if (b == null) {
906       return null;
907     }
908     else {
909       if (b.length() <= Integer.MAX_VALUE) {
910         return b.getBytes(1, (int) b.length());
911       }
912       else {
913         throw new SQLException("Blob too large to return as byte[]");
914       }
915     }
916 // Object ob = getRawColumn(columnIndex);
917
// if (ob == null) {
918
// return null;
919
// }
920
// else if (ob instanceof ByteLongObject) {
921
// // Return a safe copy of the byte[] array (BLOB).
922
// ByteLongObject b = (ByteLongObject) ob;
923
// byte[] barr = new byte[b.length()];
924
// System.arraycopy(b.getByteArray(), 0, barr, 0, b.length());
925
// return barr;
926
// }
927
// else {
928
// throw new SQLException("Unable to cast value in ResultSet to byte[]");
929
// }
930
}
931
932   public Date getDate(int columnIndex) throws SQLException {
933     // Wrap java.util.Date with java.sql.Date
934
java.util.Date JavaDoc d = extGetDate(columnIndex);
935     if (d != null) {
936       return new Date(d.getTime());
937     }
938     return null;
939   }
940
941   public java.sql.Time JavaDoc getTime(int columnIndex) throws SQLException {
942     // Wrap java.util.Date with java.sql.Time
943
java.util.Date JavaDoc d = extGetDate(columnIndex);
944     if (d != null) {
945       return new Time(d.getTime());
946     }
947     return null;
948   }
949
950   public java.sql.Timestamp JavaDoc getTimestamp(int columnIndex)
951                                                       throws SQLException {
952     // ISSUE: This may be incorrectly implemented....
953
// Wrap java.util.Date with java.sql.Timestamp
954
java.util.Date JavaDoc d = extGetDate(columnIndex);
955     if (d != null) {
956       return new Timestamp(d.getTime());
957     }
958     return null;
959   }
960
961
962   public java.io.InputStream JavaDoc getAsciiStream(int columnIndex)
963                                                       throws SQLException {
964     Clob c = getClob(columnIndex);
965     if (c == null) {
966       return null;
967     }
968     else {
969       return c.getAsciiStream();
970     }
971   }
972
973   /**
974    * @deprecated
975    */

976   public java.io.InputStream JavaDoc getUnicodeStream(int columnIndex)
977                                                       throws SQLException {
978     throw new SQLException("Deprecated method not supported");
979   }
980
981   public java.io.InputStream JavaDoc getBinaryStream(int columnIndex)
982                                                       throws SQLException {
983     Blob blob = getBlob(columnIndex);
984     if (blob == null) {
985       return null;
986     }
987     else {
988       return blob.getBinaryStream();
989     }
990 // Object ob = getRawColumn(columnIndex);
991
// if (ob == null) {
992
// return null;
993
// }
994
// else if (ob instanceof ByteLongObject) {
995
// ByteLongObject b = (ByteLongObject) ob;
996
// return new ByteArrayInputStream(b.getByteArray());
997
// }
998
// else {
999
// throw new SQLException(
1000
// "Unable to cast value in ResultSet to binary stream");
1001
// }
1002
}
1003
1004  //======================================================================
1005
// Methods for accessing results by column name
1006
//======================================================================
1007

1008  public String JavaDoc getString(String JavaDoc columnName) throws SQLException {
1009    return getString(findColumnIndex(columnName));
1010  }
1011
1012  public boolean getBoolean(String JavaDoc columnName) throws SQLException {
1013    return getBoolean(findColumnIndex(columnName));
1014  }
1015
1016  public byte getByte(String JavaDoc columnName) throws SQLException {
1017    return getByte(findColumnIndex(columnName));
1018  }
1019
1020  public short getShort(String JavaDoc columnName) throws SQLException {
1021    return getShort(findColumnIndex(columnName));
1022  }
1023
1024  public int getInt(String JavaDoc columnName) throws SQLException {
1025    return getInt(findColumnIndex(columnName));
1026  }
1027
1028  public long getLong(String JavaDoc columnName) throws SQLException {
1029    return getLong(findColumnIndex(columnName));
1030  }
1031
1032  public float getFloat(String JavaDoc columnName) throws SQLException {
1033    return getFloat(findColumnIndex(columnName));
1034  }
1035
1036  public double getDouble(String JavaDoc columnName) throws SQLException {
1037    return getDouble(findColumnIndex(columnName));
1038  }
1039
1040  /**
1041   * @deprecated
1042   */

1043  public BigDecimal JavaDoc getBigDecimal(String JavaDoc columnName, int scale)
1044                                                      throws SQLException {
1045    return getBigDecimal(findColumnIndex(columnName));
1046  }
1047
1048  public byte[] getBytes(String JavaDoc columnName) throws SQLException {
1049    return getBytes(findColumnIndex(columnName));
1050  }
1051
1052  public java.sql.Date JavaDoc getDate(String JavaDoc columnName) throws SQLException {
1053    return getDate(findColumnIndex(columnName));
1054  }
1055
1056  public java.sql.Time JavaDoc getTime(String JavaDoc columnName) throws SQLException {
1057    return getTime(findColumnIndex(columnName));
1058  }
1059
1060  public java.sql.Timestamp JavaDoc getTimestamp(String JavaDoc columnName)
1061                                                      throws SQLException {
1062    return getTimestamp(findColumnIndex(columnName));
1063  }
1064
1065  public java.io.InputStream JavaDoc getAsciiStream(String JavaDoc columnName)
1066                                                      throws SQLException {
1067    return getAsciiStream(findColumnIndex(columnName));
1068  }
1069
1070  /**
1071   * @deprecated
1072   */

1073  public java.io.InputStream JavaDoc getUnicodeStream(String JavaDoc columnName)
1074                                                      throws SQLException {
1075    return getUnicodeStream(findColumnIndex(columnName));
1076  }
1077
1078  public java.io.InputStream JavaDoc getBinaryStream(String JavaDoc columnName)
1079                                                      throws SQLException {
1080    return getBinaryStream(findColumnIndex(columnName));
1081  }
1082
1083  //=====================================================================
1084
// Advanced features:
1085
//=====================================================================
1086

1087  public SQLWarning getWarnings() throws SQLException {
1088    return head_warning;
1089  }
1090
1091  public void clearWarnings() throws SQLException {
1092    head_warning = null;
1093  }
1094
1095  public String JavaDoc getCursorName() throws SQLException {
1096    // Cursor not supported...
1097
throw MSQLException.unsupported();
1098  }
1099
1100  public ResultSetMetaData getMetaData() throws SQLException {
1101    return new MResultSetMetaData(this);
1102  }
1103
1104  public Object JavaDoc getObject(int columnIndex) throws SQLException {
1105    Object JavaDoc ob = getRawColumn(columnIndex);
1106    if (ob == null) {
1107      return ob;
1108    }
1109    if (connection.isStrictGetObject()) {
1110      // Convert depending on the column type,
1111
ColumnDescription col_desc = getColumn(columnIndex - 1);
1112      int sql_type = col_desc.getSQLType();
1113
1114      return jdbcObjectCast(ob, sql_type);
1115
1116    }
1117//#IFDEF(JDBC2.0)
1118
else {
1119      // For blobs, return an instance of Blob.
1120
if (ob instanceof ByteLongObject ||
1121          ob instanceof StreamableObject) {
1122        return asBlob(ob);
1123      }
1124    }
1125//#ENDIF
1126
return ob;
1127  }
1128
1129  public Object JavaDoc getObject(String JavaDoc columnName) throws SQLException {
1130    return getObject(findColumnIndex(columnName));
1131  }
1132
1133  //----------------------------------------------------------------
1134

1135  public int findColumn(String JavaDoc columnName) throws SQLException {
1136    return findColumnIndex(columnName);
1137  }
1138
1139  //--------------------------JDBC 2.0-----------------------------------
1140

1141  // NOTE: We allow 'getBigDecimal' methods as extensions to JDBC 1.0
1142
// because they are a key object in the Mckoi world.
1143

1144  public BigDecimal JavaDoc getBigDecimal(int columnIndex) throws SQLException {
1145    BigNumber bnum = getBigNumber(columnIndex);
1146    if (bnum != null) {
1147      return bnum.asBigDecimal();
1148    }
1149    else {
1150      return null;
1151    }
1152  }
1153  
1154  private BigNumber getBigNumber(int columnIndex) throws SQLException {
1155    Object JavaDoc ob = getRawColumn(columnIndex);
1156    if (ob == null) {
1157      return null;
1158    }
1159    if (ob instanceof BigNumber) {
1160      return (BigNumber) ob;
1161    }
1162    else {
1163      return BigNumber.fromString(makeString(ob));
1164    }
1165  }
1166
1167  public BigDecimal JavaDoc getBigDecimal(String JavaDoc columnName) throws SQLException {
1168    return getBigDecimal(findColumnIndex(columnName));
1169  }
1170
1171  // NOTE: We allow 'setFetchSize' and 'getFetchSize' as extensions to
1172
// JDBC 1.0 also.
1173

1174  public void setFetchSize(int rows) throws SQLException {
1175    if (rows > 0) {
1176      fetch_size = Math.min(rows, MAXIMUM_FETCH_SIZE);
1177    }
1178    else {
1179      fetch_size = DEFAULT_FETCH_SIZE;
1180    }
1181  }
1182
1183  public int getFetchSize() throws SQLException {
1184    return fetch_size;
1185  }
1186
1187//#IFDEF(JDBC2.0)
1188

1189  //---------------------------------------------------------------------
1190
// Getters and Setters
1191
//---------------------------------------------------------------------
1192

1193  public java.io.Reader JavaDoc getCharacterStream(int columnIndex)
1194                                                      throws SQLException {
1195    Clob c = getClob(columnIndex);
1196    if (c == null) {
1197      return null;
1198    }
1199    else {
1200      return c.getCharacterStream();
1201    }
1202  }
1203
1204  public java.io.Reader JavaDoc getCharacterStream(String JavaDoc columnName)
1205                                                      throws SQLException {
1206    return getCharacterStream(findColumnIndex(columnName));
1207  }
1208
1209
1210  //---------------------------------------------------------------------
1211
// Traversal/Positioning
1212
//---------------------------------------------------------------------
1213

1214  public boolean isBeforeFirst() throws SQLException {
1215    return real_index < 0;
1216  }
1217
1218  public boolean isAfterLast() throws SQLException {
1219    return real_index >= rowCount();
1220  }
1221
1222  public boolean isFirst() throws SQLException {
1223    return real_index == 0;
1224  }
1225
1226  public boolean isLast() throws SQLException {
1227    return real_index == rowCount() - 1;
1228  }
1229
1230  public void beforeFirst() throws SQLException {
1231    real_index = -1;
1232  }
1233
1234  public void afterLast() throws SQLException {
1235    real_index = rowCount();
1236  }
1237
1238  public boolean first() throws SQLException {
1239    real_index = 0;
1240    realIndexUpdate();
1241    return real_index < rowCount();
1242  }
1243
1244  public boolean last() throws SQLException {
1245    real_index = rowCount() - 1;
1246    realIndexUpdate();
1247    return real_index >= 0;
1248  }
1249
1250  public int getRow() throws SQLException {
1251    return real_index + 1;
1252  }
1253
1254  public boolean absolute( int row ) throws SQLException {
1255    if (row > 0) {
1256      real_index = row - 1;
1257    }
1258    else if (row < 0) {
1259      real_index = rowCount() + row;
1260    }
1261    realIndexUpdate();
1262
1263    return (real_index >= 0 && real_index < rowCount());
1264  }
1265
1266  public boolean relative( int rows ) throws SQLException {
1267    real_index += rows;
1268
1269    int row_count = rowCount();
1270    if (real_index < -1) {
1271      real_index = -1;
1272    }
1273    if (real_index > row_count) {
1274      real_index = row_count;
1275    }
1276    realIndexUpdate();
1277
1278    return (real_index >= 0 && real_index < rowCount());
1279  }
1280
1281  public boolean previous() throws SQLException {
1282    if (real_index >= 0) {
1283      --real_index;
1284      realIndexUpdate();
1285    }
1286
1287    return real_index >= 0;
1288  }
1289
1290  public void setFetchDirection(int direction) throws SQLException {
1291    // Currently ignored...
1292
// We could improve cache performance with this hint.
1293
}
1294
1295  public int getFetchDirection() throws SQLException {
1296    // Return default...
1297
// We could improve cache performance with this hint.
1298
return FETCH_UNKNOWN;
1299  }
1300
1301  public int getType() throws SQLException {
1302    // Supports scrolling but can't change
1303
return TYPE_SCROLL_INSENSITIVE;
1304  }
1305
1306  public int getConcurrency() throws SQLException {
1307    // Only support read only result sets...
1308
return CONCUR_READ_ONLY;
1309  }
1310
1311  //---------------------------------------------------------------------
1312
// Updates
1313
//---------------------------------------------------------------------
1314

1315  public boolean rowUpdated() throws SQLException {
1316    throw MSQLException.unsupported();
1317  }
1318
1319  public boolean rowInserted() throws SQLException {
1320    throw MSQLException.unsupported();
1321  }
1322
1323  public boolean rowDeleted() throws SQLException {
1324    throw MSQLException.unsupported();
1325  }
1326
1327  public void updateNull(int columnIndex) throws SQLException {
1328    throw MSQLException.unsupported();
1329  }
1330
1331  public void updateBoolean(int columnIndex, boolean x) throws SQLException {
1332    throw MSQLException.unsupported();
1333  }
1334
1335  public void updateByte(int columnIndex, byte x) throws SQLException {
1336    throw MSQLException.unsupported();
1337  }
1338
1339  public void updateShort(int columnIndex, short x) throws SQLException {
1340    throw MSQLException.unsupported();
1341  }
1342
1343  public void updateInt(int columnIndex, int x) throws SQLException {
1344    throw MSQLException.unsupported();
1345  }
1346
1347  public void updateLong(int columnIndex, long x) throws SQLException {
1348    throw MSQLException.unsupported();
1349  }
1350
1351  public void updateFloat(int columnIndex, float x) throws SQLException {
1352    throw MSQLException.unsupported();
1353  }
1354
1355  public void updateDouble(int columnIndex, double x) throws SQLException {
1356    throw MSQLException.unsupported();
1357  }
1358
1359  public void updateBigDecimal(int columnIndex, BigDecimal JavaDoc x)
1360                                                      throws SQLException {
1361    throw MSQLException.unsupported();
1362  }
1363
1364  public void updateString(int columnIndex, String JavaDoc x) throws SQLException {
1365    throw MSQLException.unsupported();
1366  }
1367
1368  public void updateBytes(int columnIndex, byte x[]) throws SQLException {
1369    throw MSQLException.unsupported();
1370  }
1371
1372  public void updateDate(int columnIndex, java.sql.Date JavaDoc x)
1373                                                      throws SQLException {
1374    throw MSQLException.unsupported();
1375  }
1376
1377  public void updateTime(int columnIndex, java.sql.Time JavaDoc x)
1378                                                      throws SQLException {
1379    throw MSQLException.unsupported();
1380  }
1381
1382  public void updateTimestamp(int columnIndex, java.sql.Timestamp JavaDoc x)
1383                                                      throws SQLException {
1384    throw MSQLException.unsupported();
1385  }
1386
1387  public void updateAsciiStream(int columnIndex,
1388                                java.io.InputStream JavaDoc x,
1389                                int length) throws SQLException {
1390    throw MSQLException.unsupported();
1391  }
1392
1393  public void updateBinaryStream(int columnIndex,
1394                                 java.io.InputStream JavaDoc x,
1395                                 int length) throws SQLException {
1396    throw MSQLException.unsupported();
1397  }
1398
1399  public void updateCharacterStream(int columnIndex,
1400                                    java.io.Reader JavaDoc x,
1401                                    int length) throws SQLException {
1402    throw MSQLException.unsupported();
1403  }
1404
1405  public void updateObject(int columnIndex, Object JavaDoc x, int scale)
1406                                                      throws SQLException {
1407    throw MSQLException.unsupported();
1408  }
1409
1410  public void updateObject(int columnIndex, Object JavaDoc x) throws SQLException {
1411    throw MSQLException.unsupported();
1412  }
1413
1414  public void updateNull(String JavaDoc columnName) throws SQLException {
1415    throw MSQLException.unsupported();
1416  }
1417
1418  public void updateBoolean(String JavaDoc columnName, boolean x)
1419                                                      throws SQLException {
1420    throw MSQLException.unsupported();
1421  }
1422
1423  public void updateByte(String JavaDoc columnName, byte x) throws SQLException {
1424    throw MSQLException.unsupported();
1425  }
1426
1427  public void updateShort(String JavaDoc columnName, short x) throws SQLException {
1428    throw MSQLException.unsupported();
1429  }
1430
1431  public void updateInt(String JavaDoc columnName, int x) throws SQLException {
1432    throw MSQLException.unsupported();
1433  }
1434
1435  public void updateLong(String JavaDoc columnName, long x) throws SQLException {
1436    throw MSQLException.unsupported();
1437  }
1438
1439  public void updateFloat(String JavaDoc columnName, float x) throws SQLException {
1440    throw MSQLException.unsupported();
1441  }
1442
1443  public void updateDouble(String JavaDoc columnName, double x) throws SQLException {
1444    throw MSQLException.unsupported();
1445  }
1446
1447  public void updateBigDecimal(String JavaDoc columnName, BigDecimal JavaDoc x)
1448                                                      throws SQLException {
1449    throw MSQLException.unsupported();
1450  }
1451
1452  public void updateString(String JavaDoc columnName, String JavaDoc x)
1453                                                      throws SQLException {
1454    throw MSQLException.unsupported();
1455  }
1456
1457  public void updateBytes(String JavaDoc columnName, byte x[]) throws SQLException {
1458    throw MSQLException.unsupported();
1459  }
1460
1461  public void updateDate(String JavaDoc columnName, java.sql.Date JavaDoc x)
1462                                                      throws SQLException {
1463    throw MSQLException.unsupported();
1464  }
1465
1466  public void updateTime(String JavaDoc columnName, java.sql.Time JavaDoc x)
1467                                                      throws SQLException {
1468    throw MSQLException.unsupported();
1469  }
1470
1471  public void updateTimestamp(String JavaDoc columnName, java.sql.Timestamp JavaDoc x)
1472                                                      throws SQLException {
1473    throw MSQLException.unsupported();
1474  }
1475
1476  public void updateAsciiStream(String JavaDoc columnName,
1477                                java.io.InputStream JavaDoc x,
1478                                int length) throws SQLException {
1479    throw MSQLException.unsupported();
1480  }
1481
1482  public void updateBinaryStream(String JavaDoc columnName,
1483                                 java.io.InputStream JavaDoc x,
1484                                 int length) throws SQLException {
1485    throw MSQLException.unsupported();
1486  }
1487
1488  public void updateCharacterStream(String JavaDoc columnName,
1489                                    java.io.Reader JavaDoc reader,
1490                                    int length) throws SQLException {
1491    throw MSQLException.unsupported();
1492  }
1493
1494  public void updateObject(String JavaDoc columnName, Object JavaDoc x, int scale)
1495                                                      throws SQLException {
1496    throw MSQLException.unsupported();
1497  }
1498
1499  public void updateObject(String JavaDoc columnName, Object JavaDoc x) throws SQLException {
1500    throw MSQLException.unsupported();
1501  }
1502
1503  public void insertRow() throws SQLException {
1504    throw MSQLException.unsupported();
1505  }
1506
1507  public void updateRow() throws SQLException {
1508    throw MSQLException.unsupported();
1509  }
1510
1511  public void deleteRow() throws SQLException {
1512    throw MSQLException.unsupported();
1513  }
1514
1515  public void refreshRow() throws SQLException {
1516    throw MSQLException.unsupported();
1517  }
1518
1519  public void cancelRowUpdates() throws SQLException {
1520    throw MSQLException.unsupported();
1521  }
1522
1523  public void moveToInsertRow() throws SQLException {
1524    throw MSQLException.unsupported();
1525  }
1526
1527  public void moveToCurrentRow() throws SQLException {
1528    throw MSQLException.unsupported();
1529  }
1530
1531  public Statement getStatement() throws SQLException {
1532    return statement;
1533  }
1534
1535  public Object JavaDoc getObject(int i, java.util.Map JavaDoc map) throws SQLException {
1536    // Haven't had time to research what exactly needs to be stored in the
1537
// map, so I'm defaulting this to 'getObject'
1538
return getObject(i);
1539  }
1540
1541  public Ref getRef(int i) throws SQLException {
1542    // Interesting idea this... Can't really see the applications of it
1543
// though unless you dealing with a really big cell and you just want to
1544
// pass around the reference rather than the actual cell contents.
1545
// Easy to fudge an implementation for this if an application needs it.
1546
throw MSQLException.unsupported();
1547  }
1548
1549  public Blob getBlob(int i) throws SQLException {
1550    // I'm assuming we must return 'null' for a null blob....
1551
Object JavaDoc ob = getRawColumn(i);
1552    if (ob != null) {
1553      try {
1554        return asBlob(ob);
1555      }
1556      catch (ClassCastException JavaDoc e) {
1557        throw new SQLException("Column " + i + " is not a binary column.");
1558      }
1559    }
1560    return null;
1561  }
1562
1563  public Clob getClob(int i) throws SQLException {
1564    // I'm assuming we must return 'null' for a null clob....
1565
Object JavaDoc ob = getRawColumn(i);
1566    if (ob != null) {
1567      try {
1568        return asClob(ob);
1569      }
1570      catch (ClassCastException JavaDoc e) {
1571        throw new SQLException("Column " + i + " is not a character column.");
1572      }
1573    }
1574    return null;
1575  }
1576
1577  public Array getArray(int i) throws SQLException {
1578    // Arrays not available in database...
1579
throw MSQLException.unsupported();
1580  }
1581
1582  public Object JavaDoc getObject(String JavaDoc colName, java.util.Map JavaDoc map)
1583                                                       throws SQLException {
1584    // Haven't had time to research what exactly needs to be stored in the
1585
// map, so I'm defaulting this to 'getObject'
1586
return getObject(colName);
1587  }
1588
1589  public Ref getRef(String JavaDoc colName) throws SQLException {
1590    throw MSQLException.unsupported();
1591  }
1592
1593  public Blob getBlob(String JavaDoc colName) throws SQLException {
1594    return getBlob(findColumnIndex(colName));
1595  }
1596
1597  public Clob getClob(String JavaDoc colName) throws SQLException {
1598    return getClob(findColumnIndex(colName));
1599  }
1600
1601  public Array getArray(String JavaDoc colName) throws SQLException {
1602    throw MSQLException.unsupported();
1603  }
1604
1605  public java.sql.Date JavaDoc getDate(int columnIndex, Calendar JavaDoc cal)
1606                                                       throws SQLException {
1607    return getDate(columnIndex);
1608  }
1609
1610  public java.sql.Date JavaDoc getDate(String JavaDoc columnName, Calendar JavaDoc cal)
1611                                                       throws SQLException {
1612    return getDate(columnName);
1613  }
1614
1615  public java.sql.Time JavaDoc getTime(int columnIndex, Calendar JavaDoc cal)
1616                                                       throws SQLException {
1617    return getTime(columnIndex);
1618  }
1619
1620  public java.sql.Time JavaDoc getTime(String JavaDoc columnName, Calendar JavaDoc cal)
1621                                                       throws SQLException {
1622    return getTime(columnName);
1623  }
1624
1625  public java.sql.Timestamp JavaDoc getTimestamp(int columnIndex, Calendar JavaDoc cal)
1626                                                       throws SQLException {
1627    return getTimestamp(columnIndex);
1628  }
1629
1630  public java.sql.Timestamp JavaDoc getTimestamp(String JavaDoc columnName, Calendar JavaDoc cal)
1631                                                       throws SQLException {
1632    return getTimestamp(columnName);
1633  }
1634
1635//#ENDIF
1636

1637//#IFDEF(JDBC3.0)
1638

1639  //-------------------------- JDBC 3.0 ----------------------------------------
1640

1641  public java.net.URL JavaDoc getURL(int columnIndex) throws SQLException {
1642    throw MSQLException.unsupported();
1643  }
1644
1645  public java.net.URL JavaDoc getURL(String JavaDoc columnName) throws SQLException {
1646    throw MSQLException.unsupported();
1647  }
1648
1649  public void updateRef(int columnIndex, java.sql.Ref JavaDoc x) throws SQLException {
1650    throw MSQLException.unsupported();
1651  }
1652
1653  public void updateRef(String JavaDoc columnName, java.sql.Ref JavaDoc x)
1654                                                         throws SQLException {
1655    throw MSQLException.unsupported();
1656  }
1657
1658  public void updateBlob(int columnIndex, java.sql.Blob JavaDoc x)
1659                                                         throws SQLException {
1660    throw MSQLException.unsupported();
1661  }
1662
1663  public void updateBlob(String JavaDoc columnName, java.sql.Blob JavaDoc x)
1664                                                         throws SQLException {
1665    throw MSQLException.unsupported();
1666  }
1667
1668  public void updateClob(int columnIndex, java.sql.Clob JavaDoc x)
1669                                                         throws SQLException {
1670    throw MSQLException.unsupported();
1671  }
1672
1673  public void updateClob(String JavaDoc columnName, java.sql.Clob JavaDoc x)
1674                                                         throws SQLException {
1675    throw MSQLException.unsupported();
1676  }
1677
1678  public void updateArray(int columnIndex, java.sql.Array JavaDoc x)
1679                                                         throws SQLException {
1680    throw MSQLException.unsupported();
1681  }
1682
1683  public void updateArray(String JavaDoc columnName, java.sql.Array JavaDoc x)
1684                                                         throws SQLException {
1685    throw MSQLException.unsupported();
1686  }
1687
1688//#ENDIF
1689

1690  // ---------- Finalize ----------
1691

1692  public void finalize() {
1693    dispose();
1694  }
1695
1696}
1697
Popular Tags