KickJava   Java API By Example, From Geeks To Geeks.

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


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.UnsupportedEncodingException JavaDoc;
22
23 import java.math.BigDecimal JavaDoc;
24
25 import java.sql.SQLException JavaDoc;
26
27 import java.util.ArrayList JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import java.util.List JavaDoc;
30
31
32 /**
33  * A result set that is updatable.
34  *
35  * @author Mark Matthews
36  */

37 public class UpdatableResultSet extends ResultSet {
38     /** Marker for 'stream' data when doing INSERT rows */
39     private final static byte[] STREAM_DATA_MARKER = "** STREAM DATA **"
40         .getBytes();
41
42     /** List of primary keys */
43     private List JavaDoc primaryKeyIndicies = null;
44
45     /** PreparedStatement used to delete data */
46     private com.mysql.jdbc.PreparedStatement deleter = null;
47
48     /** PreparedStatement used to insert data */
49     private com.mysql.jdbc.PreparedStatement inserter = null;
50
51     /** PreparedStatement used to refresh data */
52     private com.mysql.jdbc.PreparedStatement refresher;
53
54     /** PreparedStatement used to delete data */
55     private com.mysql.jdbc.PreparedStatement updater = null;
56     private SingleByteCharsetConverter charConverter;
57     private String JavaDoc charEncoding;
58     private String JavaDoc deleteSQL = null;
59     private String JavaDoc insertSQL = null;
60     private String JavaDoc quotedIdChar = null;
61     private String JavaDoc refreshSQL = null;
62     private String JavaDoc tableName;
63
64     /** SQL for in-place modifcation */
65     private String JavaDoc updateSQL = null;
66
67     /** What is the default value for the column? */
68     private byte[][] defaultColumnValue;
69
70     /** The binary data for the 'current' row */
71     private byte[][] savedCurrentRow;
72
73     /** Is this result set updateable? */
74     private boolean isUpdatable = false;
75
76     /**
77      * Creates a new UpdatableResultSet object.
78      *
79      * @param updateCount DOCUMENT ME!
80      * @param updateID DOCUMENT ME!
81      */

82     public UpdatableResultSet(long updateCount, long updateID) {
83         super(updateCount, updateID);
84     }
85
86     // ****************************************************************
87
//
88
// END OF PUBLIC INTERFACE
89
//
90
// ****************************************************************
91

92     /**
93      * Create a new ResultSet - Note that we create ResultSets to represent the
94      * results of everything.
95      *
96      * @param catalog the database in use when this result set was created
97      * @param fields an array of Field objects (basically, the ResultSet
98      * MetaData)
99      * @param rows Vector of the actual data
100      * @param conn the status string returned from the back end
101      *
102      * @throws SQLException DOCUMENT ME!
103      */

104     public UpdatableResultSet(String JavaDoc catalog, Field[] fields, RowData rows,
105         com.mysql.jdbc.Connection conn) throws SQLException JavaDoc {
106         super(catalog, fields, rows, conn);
107         isUpdatable = checkUpdatability();
108     }
109
110     /**
111      * Creates a new UpdatableResultSet object.
112      *
113      * @param fields DOCUMENT ME!
114      * @param rows DOCUMENT ME!
115      *
116      * @throws SQLException DOCUMENT ME!
117      */

118     public UpdatableResultSet(Field[] fields, RowData rows)
119         throws SQLException JavaDoc {
120         super(fields, rows);
121         isUpdatable = checkUpdatability();
122     }
123
124     /**
125      * JDBC 2.0
126      *
127      * <p>
128      * Determine if the cursor is after the last row in the result set.
129      * </p>
130      *
131      * @return true if after the last row, false otherwise. Returns false when
132      * the result set contains no rows.
133      *
134      * @exception SQLException if a database-access error occurs.
135      */

136     public synchronized boolean isAfterLast() throws SQLException JavaDoc {
137         return super.isAfterLast();
138     }
139
140     /**
141      * JDBC 2.0
142      *
143      * <p>
144      * Determine if the cursor is before the first row in the result set.
145      * </p>
146      *
147      * @return true if before the first row, false otherwise. Returns false
148      * when the result set contains no rows.
149      *
150      * @exception SQLException if a database-access error occurs.
151      */

152     public synchronized boolean isBeforeFirst() throws SQLException JavaDoc {
153         return super.isBeforeFirst();
154     }
155
156     /**
157      * JDBC 2.0 Return the concurrency of this result set. The concurrency
158      * used is determined by the statement that created the result set.
159      *
160      * @return the concurrency type, CONCUR_READ_ONLY, etc.
161      *
162      * @exception SQLException if a database-access error occurs
163      */

164     public int getConcurrency() throws SQLException JavaDoc {
165         return (isUpdatable ? CONCUR_UPDATABLE : CONCUR_READ_ONLY);
166     }
167
168     /**
169      * JDBC 2.0
170      *
171      * <p>
172      * Determine if the cursor is on the first row of the result set.
173      * </p>
174      *
175      * @return true if on the first row, false otherwise.
176      *
177      * @exception SQLException if a database-access error occurs.
178      */

179     public synchronized boolean isFirst() throws SQLException JavaDoc {
180         return super.isFirst();
181     }
182
183     /**
184      * JDBC 2.0
185      *
186      * <p>
187      * Determine if the cursor is on the last row of the result set. Note:
188      * Calling isLast() may be expensive since the JDBC driver might need to
189      * fetch ahead one row in order to determine whether the current row is
190      * the last row in the result set.
191      * </p>
192      *
193      * @return true if on the last row, false otherwise.
194      *
195      * @exception SQLException if a database-access error occurs.
196      */

197     public synchronized boolean isLast() throws SQLException JavaDoc {
198         return super.isLast();
199     }
200
201     /**
202      * JDBC 2.0
203      *
204      * <p>
205      * Move to an absolute row number in the result set.
206      * </p>
207      *
208      * <p>
209      * If row is positive, moves to an absolute row with respect to the
210      * beginning of the result set. The first row is row 1, the second is row
211      * 2, etc.
212      * </p>
213      *
214      * <p>
215      * If row is negative, moves to an absolute row position with respect to
216      * the end of result set. For example, calling absolute(-1) positions the
217      * cursor on the last row, absolute(-2) indicates the next-to-last row,
218      * etc.
219      * </p>
220      *
221      * <p>
222      * An attempt to position the cursor beyond the first/last row in the
223      * result set, leaves the cursor before/after the first/last row,
224      * respectively.
225      * </p>
226      *
227      * <p>
228      * Note: Calling absolute(1) is the same as calling first(). Calling
229      * absolute(-1) is the same as calling last().
230      * </p>
231      *
232      * @param row DOCUMENT ME!
233      *
234      * @return true if on the result set, false if off.
235      *
236      * @exception SQLException if a database-access error occurs, or row is 0,
237      * or result set type is TYPE_FORWARD_ONLY.
238      */

239     public synchronized boolean absolute(int row) throws SQLException JavaDoc {
240         return super.absolute(row);
241     }
242
243     /**
244      * JDBC 2.0
245      *
246      * <p>
247      * Moves to the end of the result set, just after the last row. Has no
248      * effect if the result set contains no rows.
249      * </p>
250      *
251      * @exception SQLException if a database-access error occurs, or result set
252      * type is TYPE_FORWARD_ONLY.
253      */

254     public synchronized void afterLast() throws SQLException JavaDoc {
255         super.afterLast();
256     }
257
258     /**
259      * JDBC 2.0
260      *
261      * <p>
262      * Moves to the front of the result set, just before the first row. Has no
263      * effect if the result set contains no rows.
264      * </p>
265      *
266      * @exception SQLException if a database-access error occurs, or result set
267      * type is TYPE_FORWARD_ONLY
268      */

269     public synchronized void beforeFirst() throws SQLException JavaDoc {
270         super.beforeFirst();
271     }
272
273     /**
274      * JDBC 2.0 The cancelRowUpdates() method may be called after calling an
275      * updateXXX() method(s) and before calling updateRow() to rollback the
276      * updates made to a row. If no updates have been made or updateRow()
277      * has already been called, then this method has no effect.
278      *
279      * @exception SQLException if a database-access error occurs, or if called
280      * when on the insert row.
281      */

282     public synchronized void cancelRowUpdates() throws SQLException JavaDoc {
283         if (doingUpdates) {
284             doingUpdates = false;
285             updater.clearParameters();
286         }
287     }
288
289     /**
290      * After this call, getWarnings returns null until a new warning is
291      * reported for this ResultSet
292      *
293      * @exception java.sql.SQLException if a database access error occurs
294      */

295     public synchronized void clearWarnings() throws java.sql.SQLException JavaDoc {
296         warningChain = null;
297     }
298
299     /**
300      * In some cases, it is desirable to immediately release a ResultSet
301      * database and JDBC resources instead of waiting for this to happen when
302      * it is automatically closed. The close method provides this immediate
303      * release.
304      *
305      * <p>
306      * <B>Note:</B> A ResultSet is automatically closed by the Statement the
307      * Statement that generated it when that Statement is closed, re-executed,
308      * or is used to retrieve the next result from a sequence of multiple
309      * results. A ResultSet is also automatically closed when it is garbage
310      * collected.
311      * </p>
312      *
313      * @exception java.sql.SQLException if a database access error occurs
314      */

315     public synchronized void close() throws java.sql.SQLException JavaDoc {
316         super.close();
317     }
318
319     /**
320      * JDBC 2.0 Delete the current row from the result set and the underlying
321      * database. Cannot be called when on the insert row.
322      *
323      * @exception SQLException if a database-access error occurs, or if called
324      * when on the insert row.
325      * @throws SQLException if the ResultSet is not updatable or some other
326      * error occurs
327      */

328     public synchronized void deleteRow() throws SQLException JavaDoc {
329         if (!isUpdatable) {
330             throw new NotUpdatable();
331         }
332
333         if (onInsertRow) {
334             throw new SQLException JavaDoc(
335                 "Can not call deleteRow() when on insert row");
336         } else if (rowData.size() == 0) {
337             throw new SQLException JavaDoc("Can't deleteRow() on empty result set");
338         } else if (isBeforeFirst()) {
339             throw new SQLException JavaDoc(
340                 "Before start of result set. Can not call deleteRow().");
341         } else if (isAfterLast()) {
342             throw new SQLException JavaDoc(
343                 "After end of result set. Can not call deleteRow().");
344         }
345
346         if (deleter == null) {
347             if (deleteSQL == null) {
348                 generateStatements();
349             }
350
351             deleter = (com.mysql.jdbc.PreparedStatement) connection
352                 .prepareStatement(deleteSQL);
353             
354             if (deleter.getMaxRows() != 0) {
355                 deleter.setMaxRows(0);
356             }
357         }
358
359         deleter.clearParameters();
360
361         String JavaDoc characterEncoding = null;
362
363         if (connection.useUnicode()) {
364             characterEncoding = connection.getEncoding();
365         }
366
367         //
368
// FIXME: Use internal routines where possible for character
369
// conversion!
370
try {
371             int numKeys = primaryKeyIndicies.size();
372
373             if (numKeys == 1) {
374                 int index = ((Integer JavaDoc) primaryKeyIndicies.get(0)).intValue();
375                 String JavaDoc currentVal = ((characterEncoding == null)
376                     ? new String JavaDoc(thisRow[index])
377                     : new String JavaDoc(thisRow[index], characterEncoding));
378                 deleter.setString(1, currentVal);
379             } else {
380                 for (int i = 0; i < numKeys; i++) {
381                     int index = ((Integer JavaDoc) primaryKeyIndicies.get(i)).intValue();
382                     String JavaDoc currentVal = ((characterEncoding == null)
383                         ? new String JavaDoc(thisRow[index])
384                         : new String JavaDoc(thisRow[index], characterEncoding));
385                     deleter.setString(i + 1, currentVal);
386                 }
387             }
388
389             deleter.executeUpdate();
390             rowData.removeRow(rowData.getCurrentRowNumber());
391         } catch (java.io.UnsupportedEncodingException JavaDoc encodingEx) {
392             throw new SQLException JavaDoc("Unsupported character encoding '"
393                 + connection.getEncoding() + "'");
394         }
395     }
396
397     /**
398      * JDBC 2.0
399      *
400      * <p>
401      * Moves to the first row in the result set.
402      * </p>
403      *
404      * @return true if on a valid row, false if no rows in the result set.
405      *
406      * @exception SQLException if a database-access error occurs, or result set
407      * type is TYPE_FORWARD_ONLY.
408      */

409     public synchronized boolean first() throws SQLException JavaDoc {
410         return super.first();
411     }
412
413     /**
414      * JDBC 2.0 Insert the contents of the insert row into the result set and
415      * the database. Must be on the insert row when this method is called.
416      *
417      * @exception SQLException if a database-access error occurs, if called
418      * when not on the insert row, or if all non-nullable columns
419      * in the insert row have not been given a value
420      */

421     public synchronized void insertRow() throws SQLException JavaDoc {
422         if (!onInsertRow) {
423             throw new SQLException JavaDoc("Not on insert row");
424         } else {
425             inserter.executeUpdate();
426
427             int numPrimaryKeys = 0;
428
429             if (primaryKeyIndicies != null) {
430                 numPrimaryKeys = primaryKeyIndicies.size();
431             }
432
433             long autoIncrementId = inserter.getLastInsertID();
434             int numFields = fields.length;
435             byte[][] newRow = new byte[numFields][];
436
437             for (int i = 0; i < numFields; i++) {
438                 if (inserter.isNull(i)) {
439                     newRow[i] = null;
440                 } else {
441                     newRow[i] = inserter.getBytes(i);
442                 }
443
444                 if ((numPrimaryKeys == 1) && fields[i].isPrimaryKey()
445                         && (autoIncrementId > 0)) {
446                     newRow[i] = String.valueOf(autoIncrementId).getBytes();
447                 }
448             }
449
450             rowData.addRow(newRow);
451             resetInserter();
452         }
453     }
454
455     /**
456      * JDBC 2.0
457      *
458      * <p>
459      * Moves to the last row in the result set.
460      * </p>
461      *
462      * @return true if on a valid row, false if no rows in the result set.
463      *
464      * @exception SQLException if a database-access error occurs, or result set
465      * type is TYPE_FORWARD_ONLY.
466      */

467     public synchronized boolean last() throws SQLException JavaDoc {
468         return super.last();
469     }
470
471     /**
472      * JDBC 2.0 Move the cursor to the remembered cursor position, usually the
473      * current row. Has no effect unless the cursor is on the insert row.
474      *
475      * @exception SQLException if a database-access error occurs, or the result
476      * set is not updatable
477      * @throws SQLException if the ResultSet is not updatable or some other
478      * error occurs
479      */

480     public synchronized void moveToCurrentRow() throws SQLException JavaDoc {
481         if (!isUpdatable) {
482             throw new NotUpdatable();
483         }
484
485         if (this.onInsertRow) {
486             onInsertRow = false;
487             this.thisRow = this.savedCurrentRow;
488         }
489     }
490
491     /**
492      * JDBC 2.0 Move to the insert row. The current cursor position is
493      * remembered while the cursor is positioned on the insert row. The insert
494      * row is a special row associated with an updatable result set. It is
495      * essentially a buffer where a new row may be constructed by calling the
496      * updateXXX() methods prior to inserting the row into the result set.
497      * Only the updateXXX(), getXXX(), and insertRow() methods may be called
498      * when the cursor is on the insert row. All of the columns in a result
499      * set must be given a value each time this method is called before
500      * calling insertRow(). UpdateXXX()must be called before getXXX() on a
501      * column.
502      *
503      * @exception SQLException if a database-access error occurs, or the result
504      * set is not updatable
505      * @throws NotUpdatable DOCUMENT ME!
506      */

507     public synchronized void moveToInsertRow() throws SQLException JavaDoc {
508         if (!this.isUpdatable) {
509             throw new NotUpdatable();
510         }
511
512         if (this.inserter == null) {
513             generateStatements();
514             this.inserter = (com.mysql.jdbc.PreparedStatement) connection
515                 .prepareStatement(this.insertSQL);
516             
517             if (this.inserter.getMaxRows() != 0) {
518                 this.inserter.setMaxRows(0);
519             }
520             
521             extractDefaultValues();
522             resetInserter();
523         } else {
524             resetInserter();
525         }
526
527         int numFields = this.fields.length;
528         
529         this.onInsertRow = true;
530         this.doingUpdates = false;
531         this.savedCurrentRow = this.thisRow;
532         this.thisRow = new byte[numFields][];
533                
534         for (int i = 0; i < numFields; i++) {
535             if (this.defaultColumnValue[i] != null) {
536                 this.inserter.setBytes(i + 1, this.defaultColumnValue[i]);
537                 
538                 // This value _could_ be changed from a getBytes(), so we
539
// need a copy....
540
byte[] defaultValueCopy = new byte[this.defaultColumnValue[i].length];
541                 System.arraycopy(defaultColumnValue[i], 0, defaultValueCopy, 0, defaultValueCopy.length);
542                 this.thisRow[i] = defaultValueCopy;
543             } else {
544                 this.inserter.setNull(i + 1, java.sql.Types.NULL);
545                 this.thisRow[i] = null;
546             }
547         }
548     }
549
550     /**
551      * A ResultSet is initially positioned before its first row, the first call
552      * to next makes the first row the current row; the second call makes the
553      * second row the current row, etc.
554      *
555      * <p>
556      * If an input stream from the previous row is open, it is implicitly
557      * closed. The ResultSet's warning chain is cleared when a new row is
558      * read
559      * </p>
560      *
561      * @return true if the new current is valid; false if there are no more
562      * rows
563      *
564      * @exception java.sql.SQLException if a database access error occurs
565      */

566     public synchronized boolean next() throws java.sql.SQLException JavaDoc {
567         return super.next();
568     }
569
570     /**
571      * The prev method is not part of JDBC, but because of the architecture of
572      * this driver it is possible to move both forward and backward within the
573      * result set.
574      *
575      * <p>
576      * If an input stream from the previous row is open, it is implicitly
577      * closed. The ResultSet's warning chain is cleared when a new row is
578      * read
579      * </p>
580      *
581      * @return true if the new current is valid; false if there are no more
582      * rows
583      *
584      * @exception java.sql.SQLException if a database access error occurs
585      */

586     public synchronized boolean prev() throws java.sql.SQLException JavaDoc {
587         return super.prev();
588     }
589
590     /**
591      * JDBC 2.0
592      *
593      * <p>
594      * Moves to the previous row in the result set.
595      * </p>
596      *
597      * <p>
598      * Note: previous() is not the same as relative(-1) since it makes sense to
599      * call previous() when there is no current row.
600      * </p>
601      *
602      * @return true if on a valid row, false if off the result set.
603      *
604      * @exception SQLException if a database-access error occurs, or result set
605      * type is TYPE_FORWAR_DONLY.
606      */

607     public synchronized boolean previous() throws SQLException JavaDoc {
608         return super.previous();
609     }
610
611     /**
612      * JDBC 2.0 Refresh the value of the current row with its current value in
613      * the database. Cannot be called when on the insert row. The
614      * refreshRow() method provides a way for an application to explicitly
615      * tell the JDBC driver to refetch a row(s) from the database. An
616      * application may want to call refreshRow() when caching or prefetching
617      * is being done by the JDBC driver to fetch the latest value of a row
618      * from the database. The JDBC driver may actually refresh multiple rows
619      * at once if the fetch size is greater than one. All values are
620      * refetched subject to the transaction isolation level and cursor
621      * sensitivity. If refreshRow() is called after calling updateXXX(), but
622      * before calling updateRow() then the updates made to the row are lost.
623      * Calling refreshRow() frequently will likely slow performance.
624      *
625      * @exception SQLException if a database-access error occurs, or if called
626      * when on the insert row.
627      * @throws NotUpdatable DOCUMENT ME!
628      */

629     public synchronized void refreshRow() throws SQLException JavaDoc {
630         if (!isUpdatable) {
631             throw new NotUpdatable();
632         }
633
634         if (onInsertRow) {
635             throw new SQLException JavaDoc(
636                 "Can not call refreshRow() when on insert row");
637         } else if (rowData.size() == 0) {
638             throw new SQLException JavaDoc("Can't refreshRow() on empty result set");
639         } else if (isBeforeFirst()) {
640             throw new SQLException JavaDoc(
641                 "Before start of result set. Can not call refreshRow().");
642         } else if (isAfterLast()) {
643             throw new SQLException JavaDoc(
644                 "After end of result set. Can not call refreshRow().");
645         }
646
647         if (refresher == null) {
648             if (refreshSQL == null) {
649                 generateStatements();
650             }
651
652             refresher = (com.mysql.jdbc.PreparedStatement) connection
653                 .prepareStatement(refreshSQL);
654             
655             if (refresher.getMaxRows() != 0) {
656                 refresher.setMaxRows(0);
657             }
658         }
659
660         refresher.clearParameters();
661
662         int numKeys = primaryKeyIndicies.size();
663
664         if (numKeys == 1) {
665             byte[] dataFrom = null;
666             int index = ((Integer JavaDoc) primaryKeyIndicies.get(0)).intValue();
667
668             if (!doingUpdates) {
669                 dataFrom = thisRow[index];
670             } else {
671                 dataFrom = updater.getBytes(index);
672
673                 // Primary keys not set?
674
if (updater.isNull(index) || (dataFrom.length == 0)) {
675                     dataFrom = thisRow[index];
676                 }
677             }
678
679             refresher.setBytesNoEscape(1, dataFrom);
680         } else {
681             for (int i = 0; i < numKeys; i++) {
682                 byte[] dataFrom = null;
683                 int index = ((Integer JavaDoc) primaryKeyIndicies.get(i)).intValue();
684
685                 if (!doingUpdates) {
686                     dataFrom = thisRow[index];
687                 } else {
688                     dataFrom = updater.getBytes(index);
689
690                     // Primary keys not set?
691
if (updater.isNull(index) || (dataFrom.length == 0)) {
692                         dataFrom = thisRow[index];
693                     }
694                 }
695
696                 refresher.setBytesNoEscape(i + 1, dataFrom);
697             }
698         }
699
700         java.sql.ResultSet JavaDoc rs = null;
701
702         try {
703             rs = refresher.executeQuery();
704
705             int numCols = rs.getMetaData().getColumnCount();
706
707             if (rs.next()) {
708                 for (int i = 0; i < numCols; i++) {
709                     byte[] val = rs.getBytes(i + 1);
710
711                     if ((val == null) || rs.wasNull()) {
712                         thisRow[i] = null;
713                     } else {
714                         thisRow[i] = rs.getBytes(i + 1);
715                     }
716                 }
717             } else {
718                 throw new SQLException JavaDoc("refreshRow() called on row that has been deleted or had primary key changed",
719                     SQLError.SQL_STATE_GENERAL_ERROR);
720             }
721         } finally {
722             if (rs != null) {
723                 try {
724                     rs.close();
725                 } catch (SQLException JavaDoc ex) {
726                     ; // ignore
727
}
728             }
729         }
730     }
731
732     /**
733      * JDBC 2.0
734      *
735      * <p>
736      * Moves a relative number of rows, either positive or negative. Attempting
737      * to move beyond the first/last row in the result set positions the
738      * cursor before/after the the first/last row. Calling relative(0) is
739      * valid, but does not change the cursor position.
740      * </p>
741      *
742      * <p>
743      * Note: Calling relative(1) is different than calling next() since is
744      * makes sense to call next() when there is no current row, for example,
745      * when the cursor is positioned before the first row or after the last
746      * row of the result set.
747      * </p>
748      *
749      * @param rows DOCUMENT ME!
750      *
751      * @return true if on a row, false otherwise.
752      *
753      * @exception SQLException if a database-access error occurs, or there is
754      * no current row, or result set type is TYPE_FORWARD_ONLY.
755      */

756     public synchronized boolean relative(int rows) throws SQLException JavaDoc {
757         return super.relative(rows);
758     }
759
760     /**
761      * JDBC 2.0 Determine if this row has been deleted. A deleted row may
762      * leave a visible "hole" in a result set. This method can be used to
763      * detect holes in a result set. The value returned depends on whether or
764      * not the result set can detect deletions.
765      *
766      * @return true if deleted and deletes are detected
767      *
768      * @exception SQLException if a database-access error occurs
769      * @throws NotImplemented DOCUMENT ME!
770      *
771      * @see DatabaseMetaData#deletesAreDetected
772      */

773     public synchronized boolean rowDeleted() throws SQLException JavaDoc {
774         throw new NotImplemented();
775     }
776
777     /**
778      * JDBC 2.0 Determine if the current row has been inserted. The value
779      * returned depends on whether or not the result set can detect visible
780      * inserts.
781      *
782      * @return true if inserted and inserts are detected
783      *
784      * @exception SQLException if a database-access error occurs
785      * @throws NotImplemented DOCUMENT ME!
786      *
787      * @see DatabaseMetaData#insertsAreDetected
788      */

789     public synchronized boolean rowInserted() throws SQLException JavaDoc {
790         throw new NotImplemented();
791     }
792
793     //---------------------------------------------------------------------
794
// Updates
795
//---------------------------------------------------------------------
796

797     /**
798      * JDBC 2.0 Determine if the current row has been updated. The value
799      * returned depends on whether or not the result set can detect updates.
800      *
801      * @return true if the row has been visibly updated by the owner or
802      * another, and updates are detected
803      *
804      * @exception SQLException if a database-access error occurs
805      * @throws NotImplemented DOCUMENT ME!
806      *
807      * @see DatabaseMetaData#updatesAreDetected
808      */

809     public synchronized boolean rowUpdated() throws SQLException JavaDoc {
810         throw new NotImplemented();
811     }
812
813     /**
814      * JDBC 2.0 Update a column with an ascii stream value. The updateXXX()
815      * methods are used to update column values in the current row, or the
816      * insert row. The updateXXX() methods do not update the underlying
817      * database, instead the updateRow() or insertRow() methods are called to
818      * update the database.
819      *
820      * @param columnIndex the first column is 1, the second is 2, ...
821      * @param x the new column value
822      * @param length the length of the stream
823      *
824      * @exception SQLException if a database-access error occurs
825      */

826     public synchronized void updateAsciiStream(int columnIndex,
827         java.io.InputStream JavaDoc x, int length) throws SQLException JavaDoc {
828         if (!onInsertRow) {
829             if (!doingUpdates) {
830                 doingUpdates = true;
831                 syncUpdate();
832             }
833
834             updater.setAsciiStream(columnIndex, x, length);
835         } else {
836             inserter.setAsciiStream(columnIndex, x, length);
837             this.thisRow[columnIndex - 1] = STREAM_DATA_MARKER;
838         }
839     }
840
841     /**
842      * JDBC 2.0 Update a column with an ascii stream value. The updateXXX()
843      * methods are used to update column values in the current row, or the
844      * insert row. The updateXXX() methods do not update the underlying
845      * database, instead the updateRow() or insertRow() methods are called to
846      * update the database.
847      *
848      * @param columnName the name of the column
849      * @param x the new column value
850      * @param length of the stream
851      *
852      * @exception SQLException if a database-access error occurs
853      */

854     public synchronized void updateAsciiStream(String JavaDoc columnName,
855         java.io.InputStream JavaDoc x, int length) throws SQLException JavaDoc {
856         updateAsciiStream(findColumn(columnName), x, length);
857     }
858
859     /**
860      * JDBC 2.0 Update a column with a BigDecimal value. The updateXXX()
861      * methods are used to update column values in the current row, or the
862      * insert row. The updateXXX() methods do not update the underlying
863      * database, instead the updateRow() or insertRow() methods are called to
864      * update the database.
865      *
866      * @param columnIndex the first column is 1, the second is 2, ...
867      * @param x the new column value
868      *
869      * @exception SQLException if a database-access error occurs
870      */

871     public synchronized void updateBigDecimal(int columnIndex, BigDecimal JavaDoc x)
872         throws SQLException JavaDoc {
873         if (!onInsertRow) {
874             if (!doingUpdates) {
875                 doingUpdates = true;
876                 syncUpdate();
877             }
878
879             updater.setBigDecimal(columnIndex, x);
880         } else {
881             inserter.setBigDecimal(columnIndex, x);
882
883             if (x == null) {
884                 this.thisRow[columnIndex - 1] = null;
885             } else {
886                 this.thisRow[columnIndex - 1] = x.toString().getBytes();
887             }
888         }
889     }
890
891     /**
892      * JDBC 2.0 Update a column with a BigDecimal value. The updateXXX()
893      * methods are used to update column values in the current row, or the
894      * insert row. The updateXXX() methods do not update the underlying
895      * database, instead the updateRow() or insertRow() methods are called to
896      * update the database.
897      *
898      * @param columnName the name of the column
899      * @param x the new column value
900      *
901      * @exception SQLException if a database-access error occurs
902      */

903     public synchronized void updateBigDecimal(String JavaDoc columnName, BigDecimal JavaDoc x)
904         throws SQLException JavaDoc {
905         updateBigDecimal(findColumn(columnName), x);
906     }
907
908     /**
909      * JDBC 2.0 Update a column with a binary stream value. The updateXXX()
910      * methods are used to update column values in the current row, or the
911      * insert row. The updateXXX() methods do not update the underlying
912      * database, instead the updateRow() or insertRow() methods are called to
913      * update the database.
914      *
915      * @param columnIndex the first column is 1, the second is 2, ...
916      * @param x the new column value
917      * @param length the length of the stream
918      *
919      * @exception SQLException if a database-access error occurs
920      */

921     public synchronized void updateBinaryStream(int columnIndex,
922         java.io.InputStream JavaDoc x, int length) throws SQLException JavaDoc {
923         if (!onInsertRow) {
924             if (!doingUpdates) {
925                 doingUpdates = true;
926                 syncUpdate();
927             }
928
929             updater.setBinaryStream(columnIndex, x, length);
930         } else {
931             inserter.setBinaryStream(columnIndex, x, length);
932
933             if (x == null) {
934                 this.thisRow[columnIndex - 1] = null;
935             } else {
936                 this.thisRow[columnIndex - 1] = STREAM_DATA_MARKER;
937             }
938         }
939     }
940
941     /**
942      * JDBC 2.0 Update a column with a binary stream value. The updateXXX()
943      * methods are used to update column values in the current row, or the
944      * insert row. The updateXXX() methods do not update the underlying
945      * database, instead the updateRow() or insertRow() methods are called to
946      * update the database.
947      *
948      * @param columnName the name of the column
949      * @param x the new column value
950      * @param length of the stream
951      *
952      * @exception SQLException if a database-access error occurs
953      */

954     public synchronized void updateBinaryStream(String JavaDoc columnName,
955         java.io.InputStream JavaDoc x, int length) throws SQLException JavaDoc {
956         updateBinaryStream(findColumn(columnName), x, length);
957     }
958
959     /**
960      * @see ResultSet#updateBlob(int, Blob)
961      */

962     public void updateBlob(int columnIndex, java.sql.Blob JavaDoc blob)
963         throws SQLException JavaDoc {
964         if (!onInsertRow) {
965             if (!doingUpdates) {
966                 doingUpdates = true;
967                 syncUpdate();
968             }
969
970             updater.setBlob(columnIndex, blob);
971         } else {
972             inserter.setBlob(columnIndex, blob);
973
974             if (blob == null) {
975                 this.thisRow[columnIndex - 1] = null;
976             } else {
977                 this.thisRow[columnIndex - 1] = STREAM_DATA_MARKER;
978             }
979         }
980     }
981
982     /**
983      * @see ResultSet#updateBlob(String, Blob)
984      */

985     public void updateBlob(String JavaDoc columnName, java.sql.Blob JavaDoc blob)
986         throws SQLException JavaDoc {
987         updateBlob(findColumn(columnName), blob);
988     }
989
990     /**
991      * JDBC 2.0 Update a column with a boolean value. The updateXXX() methods
992      * are used to update column values in the current row, or the insert row.
993      * The updateXXX() methods do not update the underlying database, instead
994      * the updateRow() or insertRow() methods are called to update the
995      * database.
996      *
997      * @param columnIndex the first column is 1, the second is 2, ...
998      * @param x the new column value
999      *
1000     * @exception SQLException if a database-access error occurs
1001     */

1002    public synchronized void updateBoolean(int columnIndex, boolean x)
1003        throws SQLException JavaDoc {
1004        if (!onInsertRow) {
1005            if (!doingUpdates) {
1006                doingUpdates = true;
1007                syncUpdate();
1008            }
1009
1010            updater.setBoolean(columnIndex, x);
1011        } else {
1012            inserter.setBoolean(columnIndex, x);
1013
1014            this.thisRow[columnIndex - 1] = inserter.getBytes(1);
1015        }
1016    }
1017
1018    /**
1019     * JDBC 2.0 Update a column with a boolean value. The updateXXX() methods
1020     * are used to update column values in the current row, or the insert row.
1021     * The updateXXX() methods do not update the underlying database, instead
1022     * the updateRow() or insertRow() methods are called to update the
1023     * database.
1024     *
1025     * @param columnName the name of the column
1026     * @param x the new column value
1027     *
1028     * @exception SQLException if a database-access error occurs
1029     */

1030    public synchronized void updateBoolean(String JavaDoc columnName, boolean x)
1031        throws SQLException JavaDoc {
1032        updateBoolean(findColumn(columnName), x);
1033    }
1034
1035    /**
1036     * JDBC 2.0 Update a column with a byte value. The updateXXX() methods are
1037     * used to update column values in the current row, or the insert row. The
1038     * updateXXX() methods do not update the underlying database, instead the
1039     * updateRow() or insertRow() methods are called to update the database.
1040     *
1041     * @param columnIndex the first column is 1, the second is 2, ...
1042     * @param x the new column value
1043     *
1044     * @exception SQLException if a database-access error occurs
1045     */

1046    public synchronized void updateByte(int columnIndex, byte x)
1047        throws SQLException JavaDoc {
1048        if (!onInsertRow) {
1049            if (!doingUpdates) {
1050                doingUpdates = true;
1051                syncUpdate();
1052            }
1053
1054            updater.setByte(columnIndex, x);
1055        } else {
1056            inserter.setByte(columnIndex, x);
1057
1058            this.thisRow[columnIndex - 1] = inserter.getBytes(columnIndex);
1059        }
1060    }
1061
1062    /**
1063     * JDBC 2.0 Update a column with a byte value. The updateXXX() methods are
1064     * used to update column values in the current row, or the insert row. The
1065     * updateXXX() methods do not update the underlying database, instead the
1066     * updateRow() or insertRow() methods are called to update the database.
1067     *
1068     * @param columnName the name of the column
1069     * @param x the new column value
1070     *
1071     * @exception SQLException if a database-access error occurs
1072     */

1073    public synchronized void updateByte(String JavaDoc columnName, byte x)
1074        throws SQLException JavaDoc {
1075        updateByte(findColumn(columnName), x);
1076    }
1077
1078    /**
1079     * JDBC 2.0 Update a column with a byte array value. The updateXXX()
1080     * methods are used to update column values in the current row, or the
1081     * insert row. The updateXXX() methods do not update the underlying
1082     * database, instead the updateRow() or insertRow() methods are called to
1083     * update the database.
1084     *
1085     * @param columnIndex the first column is 1, the second is 2, ...
1086     * @param x the new column value
1087     *
1088     * @exception SQLException if a database-access error occurs
1089     */

1090    public synchronized void updateBytes(int columnIndex, byte[] x)
1091        throws SQLException JavaDoc {
1092        if (!onInsertRow) {
1093            if (!doingUpdates) {
1094                doingUpdates = true;
1095                syncUpdate();
1096            }
1097
1098            updater.setBytes(columnIndex, x);
1099        } else {
1100            inserter.setBytes(columnIndex, x);
1101
1102            this.thisRow[columnIndex - 1] = x;
1103        }
1104    }
1105
1106    /**
1107     * JDBC 2.0 Update a column with a byte array value. The updateXXX()
1108     * methods are used to update column values in the current row, or the
1109     * insert row. The updateXXX() methods do not update the underlying
1110     * database, instead the updateRow() or insertRow() methods are called to
1111     * update the database.
1112     *
1113     * @param columnName the name of the column
1114     * @param x the new column value
1115     *
1116     * @exception SQLException if a database-access error occurs
1117     */

1118    public synchronized void updateBytes(String JavaDoc columnName, byte[] x)
1119        throws SQLException JavaDoc {
1120        updateBytes(findColumn(columnName), x);
1121    }
1122
1123    /**
1124     * JDBC 2.0 Update a column with a character stream value. The updateXXX()
1125     * methods are used to update column values in the current row, or the
1126     * insert row. The updateXXX() methods do not update the underlying
1127     * database, instead the updateRow() or insertRow() methods are called to
1128     * update the database.
1129     *
1130     * @param columnIndex the first column is 1, the second is 2, ...
1131     * @param x the new column value
1132     * @param length the length of the stream
1133     *
1134     * @exception SQLException if a database-access error occurs
1135     */

1136    public synchronized void updateCharacterStream(int columnIndex,
1137        java.io.Reader JavaDoc x, int length) throws SQLException JavaDoc {
1138        if (!onInsertRow) {
1139            if (!doingUpdates) {
1140                doingUpdates = true;
1141                syncUpdate();
1142            }
1143
1144            updater.setCharacterStream(columnIndex, x, length);
1145        } else {
1146            inserter.setCharacterStream(columnIndex, x, length);
1147
1148            if (x == null) {
1149                this.thisRow[columnIndex - 1] = null;
1150            } else {
1151                this.thisRow[columnIndex - 1] = STREAM_DATA_MARKER;
1152            }
1153        }
1154    }
1155
1156    /**
1157     * JDBC 2.0 Update a column with a character stream value. The updateXXX()
1158     * methods are used to update column values in the current row, or the
1159     * insert row. The updateXXX() methods do not update the underlying
1160     * database, instead the updateRow() or insertRow() methods are called to
1161     * update the database.
1162     *
1163     * @param columnName the name of the column
1164     * @param reader the new column value
1165     * @param length of the stream
1166     *
1167     * @exception SQLException if a database-access error occurs
1168     */

1169    public synchronized void updateCharacterStream(String JavaDoc columnName,
1170        java.io.Reader JavaDoc reader, int length) throws SQLException JavaDoc {
1171        updateCharacterStream(findColumn(columnName), reader, length);
1172    }
1173    
1174    /**
1175      * @see ResultSet#updateClob(int, Clob)
1176      */

1177     public void updateClob(int columnIndex, java.sql.Clob JavaDoc clob) throws SQLException JavaDoc {
1178         if (clob == null) {
1179            updateNull(columnIndex);
1180         } else {
1181            updateCharacterStream(columnIndex, clob.getCharacterStream(), (int) clob.length());
1182         }
1183     }
1184
1185    /**
1186     * JDBC 2.0 Update a column with a Date value. The updateXXX() methods are
1187     * used to update column values in the current row, or the insert row. The
1188     * updateXXX() methods do not update the underlying database, instead the
1189     * updateRow() or insertRow() methods are called to update the database.
1190     *
1191     * @param columnIndex the first column is 1, the second is 2, ...
1192     * @param x the new column value
1193     *
1194     * @exception SQLException if a database-access error occurs
1195     */

1196    public synchronized void updateDate(int columnIndex, java.sql.Date JavaDoc x)
1197        throws SQLException JavaDoc {
1198        if (!onInsertRow) {
1199            if (!doingUpdates) {
1200                doingUpdates = true;
1201                syncUpdate();
1202            }
1203
1204            updater.setDate(columnIndex, x);
1205        } else {
1206            inserter.setDate(columnIndex, x);
1207
1208            this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex
1209                    - 1);
1210        }
1211    }
1212
1213    /**
1214     * JDBC 2.0 Update a column with a Date value. The updateXXX() methods are
1215     * used to update column values in the current row, or the insert row. The
1216     * updateXXX() methods do not update the underlying database, instead the
1217     * updateRow() or insertRow() methods are called to update the database.
1218     *
1219     * @param columnName the name of the column
1220     * @param x the new column value
1221     *
1222     * @exception SQLException if a database-access error occurs
1223     */

1224    public synchronized void updateDate(String JavaDoc columnName, java.sql.Date JavaDoc x)
1225        throws SQLException JavaDoc {
1226        updateDate(findColumn(columnName), x);
1227    }
1228
1229    /**
1230     * JDBC 2.0 Update a column with a Double value. The updateXXX() methods
1231     * are used to update column values in the current row, or the insert row.
1232     * The updateXXX() methods do not update the underlying database, instead
1233     * the updateRow() or insertRow() methods are called to update the
1234     * database.
1235     *
1236     * @param columnIndex the first column is 1, the second is 2, ...
1237     * @param x the new column value
1238     *
1239     * @exception SQLException if a database-access error occurs
1240     */

1241    public synchronized void updateDouble(int columnIndex, double x)
1242        throws SQLException JavaDoc {
1243        if (!onInsertRow) {
1244            if (!doingUpdates) {
1245                doingUpdates = true;
1246                syncUpdate();
1247            }
1248
1249            updater.setDouble(columnIndex, x);
1250        } else {
1251            inserter.setDouble(columnIndex, x);
1252
1253            this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex
1254                    - 1);
1255        }
1256    }
1257
1258    /**
1259     * JDBC 2.0 Update a column with a double value. The updateXXX() methods
1260     * are used to update column values in the current row, or the insert row.
1261     * The updateXXX() methods do not update the underlying database, instead
1262     * the updateRow() or insertRow() methods are called to update the
1263     * database.
1264     *
1265     * @param columnName the name of the column
1266     * @param x the new column value
1267     *
1268     * @exception SQLException if a database-access error occurs
1269     */

1270    public synchronized void updateDouble(String JavaDoc columnName, double x)
1271        throws SQLException JavaDoc {
1272        updateDouble(findColumn(columnName), x);
1273    }
1274
1275    /**
1276     * JDBC 2.0 Update a column with a float value. The updateXXX() methods
1277     * are used to update column values in the current row, or the insert row.
1278     * The updateXXX() methods do not update the underlying database, instead
1279     * the updateRow() or insertRow() methods are called to update the
1280     * database.
1281     *
1282     * @param columnIndex the first column is 1, the second is 2, ...
1283     * @param x the new column value
1284     *
1285     * @exception SQLException if a database-access error occurs
1286     */

1287    public synchronized void updateFloat(int columnIndex, float x)
1288        throws SQLException JavaDoc {
1289        if (!onInsertRow) {
1290            if (!doingUpdates) {
1291                doingUpdates = true;
1292                syncUpdate();
1293            }
1294
1295            updater.setFloat(columnIndex, x);
1296        } else {
1297            inserter.setFloat(columnIndex, x);
1298
1299            this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex
1300                    - 1);
1301        }
1302    }
1303
1304    /**
1305     * JDBC 2.0 Update a column with a float value. The updateXXX() methods
1306     * are used to update column values in the current row, or the insert row.
1307     * The updateXXX() methods do not update the underlying database, instead
1308     * the updateRow() or insertRow() methods are called to update the
1309     * database.
1310     *
1311     * @param columnName the name of the column
1312     * @param x the new column value
1313     *
1314     * @exception SQLException if a database-access error occurs
1315     */

1316    public synchronized void updateFloat(String JavaDoc columnName, float x)
1317        throws SQLException JavaDoc {
1318        updateFloat(findColumn(columnName), x);
1319    }
1320
1321    /**
1322     * JDBC 2.0 Update a column with an integer value. The updateXXX() methods
1323     * are used to update column values in the current row, or the insert row.
1324     * The updateXXX() methods do not update the underlying database, instead
1325     * the updateRow() or insertRow() methods are called to update the
1326     * database.
1327     *
1328     * @param columnIndex the first column is 1, the second is 2, ...
1329     * @param x the new column value
1330     *
1331     * @exception SQLException if a database-access error occurs
1332     */

1333    public synchronized void updateInt(int columnIndex, int x)
1334        throws SQLException JavaDoc {
1335        if (!onInsertRow) {
1336            if (!doingUpdates) {
1337                doingUpdates = true;
1338                syncUpdate();
1339            }
1340
1341            updater.setInt(columnIndex, x);
1342        } else {
1343            inserter.setInt(columnIndex, x);
1344
1345            this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex
1346                    - 1);
1347        }
1348    }
1349
1350    /**
1351     * JDBC 2.0 Update a column with an integer value. The updateXXX() methods
1352     * are used to update column values in the current row, or the insert row.
1353     * The updateXXX() methods do not update the underlying database, instead
1354     * the updateRow() or insertRow() methods are called to update the
1355     * database.
1356     *
1357     * @param columnName the name of the column
1358     * @param x the new column value
1359     *
1360     * @exception SQLException if a database-access error occurs
1361     */

1362    public synchronized void updateInt(String JavaDoc columnName, int x)
1363        throws SQLException JavaDoc {
1364        updateInt(findColumn(columnName), x);
1365    }
1366
1367    /**
1368     * JDBC 2.0 Update a column with a long value. The updateXXX() methods are
1369     * used to update column values in the current row, or the insert row. The
1370     * updateXXX() methods do not update the underlying database, instead the
1371     * updateRow() or insertRow() methods are called to update the database.
1372     *
1373     * @param columnIndex the first column is 1, the second is 2, ...
1374     * @param x the new column value
1375     *
1376     * @exception SQLException if a database-access error occurs
1377     */

1378    public synchronized void updateLong(int columnIndex, long x)
1379        throws SQLException JavaDoc {
1380        if (!onInsertRow) {
1381            if (!doingUpdates) {
1382                doingUpdates = true;
1383                syncUpdate();
1384            }
1385
1386            updater.setLong(columnIndex, x);
1387        } else {
1388            inserter.setLong(columnIndex, x);
1389
1390            this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex
1391                    - 1);
1392        }
1393    }
1394
1395    /**
1396     * JDBC 2.0 Update a column with a long value. The updateXXX() methods are
1397     * used to update column values in the current row, or the insert row. The
1398     * updateXXX() methods do not update the underlying database, instead the
1399     * updateRow() or insertRow() methods are called to update the database.
1400     *
1401     * @param columnName the name of the column
1402     * @param x the new column value
1403     *
1404     * @exception SQLException if a database-access error occurs
1405     */

1406    public synchronized void updateLong(String JavaDoc columnName, long x)
1407        throws SQLException JavaDoc {
1408        updateLong(findColumn(columnName), x);
1409    }
1410
1411    /**
1412     * JDBC 2.0 Give a nullable column a null value. The updateXXX() methods
1413     * are used to update column values in the current row, or the insert row.
1414     * The updateXXX() methods do not update the underlying database, instead
1415     * the updateRow() or insertRow() methods are called to update the
1416     * database.
1417     *
1418     * @param columnIndex the first column is 1, the second is 2, ...
1419     *
1420     * @exception SQLException if a database-access error occurs
1421     */

1422    public synchronized void updateNull(int columnIndex)
1423        throws SQLException JavaDoc {
1424        if (!onInsertRow) {
1425            if (!doingUpdates) {
1426                doingUpdates = true;
1427                syncUpdate();
1428            }
1429
1430            updater.setNull(columnIndex, 0);
1431        } else {
1432            inserter.setNull(columnIndex, 0);
1433
1434            this.thisRow[columnIndex - 1] = null;
1435        }
1436    }
1437
1438    /**
1439     * JDBC 2.0 Update a column with a null value. The updateXXX() methods are
1440     * used to update column values in the current row, or the insert row. The
1441     * updateXXX() methods do not update the underlying database, instead the
1442     * updateRow() or insertRow() methods are called to update the database.
1443     *
1444     * @param columnName the name of the column
1445     *
1446     * @exception SQLException if a database-access error occurs
1447     */

1448    public synchronized void updateNull(String JavaDoc columnName)
1449        throws SQLException JavaDoc {
1450        updateNull(findColumn(columnName));
1451    }
1452
1453    /**
1454     * JDBC 2.0 Update a column with an Object value. The updateXXX() methods
1455     * are used to update column values in the current row, or the insert row.
1456     * The updateXXX() methods do not update the underlying database, instead
1457     * the updateRow() or insertRow() methods are called to update the
1458     * database.
1459     *
1460     * @param columnIndex the first column is 1, the second is 2, ...
1461     * @param x the new column value
1462     * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
1463     * this is the number of digits after the decimal. For all other
1464     * types this value will be ignored.
1465     *
1466     * @exception SQLException if a database-access error occurs
1467     */

1468    public synchronized void updateObject(int columnIndex, Object JavaDoc x, int scale)
1469        throws SQLException JavaDoc {
1470        if (!onInsertRow) {
1471            if (!doingUpdates) {
1472                doingUpdates = true;
1473                syncUpdate();
1474            }
1475
1476            updater.setObject(columnIndex, x);
1477        } else {
1478            inserter.setObject(columnIndex, x);
1479
1480            this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex
1481                    - 1);
1482        }
1483    }
1484
1485    /**
1486     * JDBC 2.0 Update a column with an Object value. The updateXXX() methods
1487     * are used to update column values in the current row, or the insert row.
1488     * The updateXXX() methods do not update the underlying database, instead
1489     * the updateRow() or insertRow() methods are called to update the
1490     * database.
1491     *
1492     * @param columnIndex the first column is 1, the second is 2, ...
1493     * @param x the new column value
1494     *
1495     * @exception SQLException if a database-access error occurs
1496     */

1497    public synchronized void updateObject(int columnIndex, Object JavaDoc x)
1498        throws SQLException JavaDoc {
1499        if (!onInsertRow) {
1500            if (!doingUpdates) {
1501                doingUpdates = true;
1502                syncUpdate();
1503            }
1504
1505            updater.setObject(columnIndex, x);
1506        } else {
1507            inserter.setObject(columnIndex, x);
1508
1509            this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex
1510                    - 1);
1511        }
1512    }
1513
1514    /**
1515     * JDBC 2.0 Update a column with an Object value. The updateXXX() methods
1516     * are used to update column values in the current row, or the insert row.
1517     * The updateXXX() methods do not update the underlying database, instead
1518     * the updateRow() or insertRow() methods are called to update the
1519     * database.
1520     *
1521     * @param columnName the name of the column
1522     * @param x the new column value
1523     * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
1524     * this is the number of digits after the decimal. For all other
1525     * types this value will be ignored.
1526     *
1527     * @exception SQLException if a database-access error occurs
1528     */

1529    public synchronized void updateObject(String JavaDoc columnName, Object JavaDoc x, int scale)
1530        throws SQLException JavaDoc {
1531        updateObject(findColumn(columnName), x);
1532    }
1533
1534    /**
1535     * JDBC 2.0 Update a column with an Object value. The updateXXX() methods
1536     * are used to update column values in the current row, or the insert row.
1537     * The updateXXX() methods do not update the underlying database, instead
1538     * the updateRow() or insertRow() methods are called to update the
1539     * database.
1540     *
1541     * @param columnName the name of the column
1542     * @param x the new column value
1543     *
1544     * @exception SQLException if a database-access error occurs
1545     */

1546    public synchronized void updateObject(String JavaDoc columnName, Object JavaDoc x)
1547        throws SQLException JavaDoc {
1548        updateObject(findColumn(columnName), x);
1549    }
1550
1551    /**
1552     * JDBC 2.0 Update the underlying database with the new contents of the
1553     * current row. Cannot be called when on the insert row.
1554     *
1555     * @exception SQLException if a database-access error occurs, or if called
1556     * when on the insert row
1557     * @throws NotUpdatable DOCUMENT ME!
1558     */

1559    public synchronized void updateRow() throws SQLException JavaDoc {
1560        if (!isUpdatable) {
1561            throw new NotUpdatable();
1562        }
1563
1564        if (doingUpdates) {
1565            updater.executeUpdate();
1566            refreshRow();
1567            doingUpdates = false;
1568        }
1569
1570        //
1571
// fixes calling updateRow() and then doing more
1572
// updates on same row...
1573
syncUpdate();
1574    }
1575
1576    /**
1577     * JDBC 2.0 Update a column with a short value. The updateXXX() methods
1578     * are used to update column values in the current row, or the insert row.
1579     * The updateXXX() methods do not update the underlying database, instead
1580     * the updateRow() or insertRow() methods are called to update the
1581     * database.
1582     *
1583     * @param columnIndex the first column is 1, the second is 2, ...
1584     * @param x the new column value
1585     *
1586     * @exception SQLException if a database-access error occurs
1587     */

1588    public synchronized void updateShort(int columnIndex, short x)
1589        throws SQLException JavaDoc {
1590        if (!onInsertRow) {
1591            if (!doingUpdates) {
1592                doingUpdates = true;
1593                syncUpdate();
1594            }
1595
1596            updater.setShort(columnIndex, x);
1597        } else {
1598            inserter.setShort(columnIndex, x);
1599
1600            this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex
1601                    - 1);
1602        }
1603    }
1604
1605    /**
1606     * JDBC 2.0 Update a column with a short value. The updateXXX() methods
1607     * are used to update column values in the current row, or the insert row.
1608     * The updateXXX() methods do not update the underlying database, instead
1609     * the updateRow() or insertRow() methods are called to update the
1610     * database.
1611     *
1612     * @param columnName the name of the column
1613     * @param x the new column value
1614     *
1615     * @exception SQLException if a database-access error occurs
1616     */

1617    public synchronized void updateShort(String JavaDoc columnName, short x)
1618        throws SQLException JavaDoc {
1619        updateShort(findColumn(columnName), x);
1620    }
1621
1622    /**
1623     * JDBC 2.0 Update a column with a String value. The updateXXX() methods
1624     * are used to update column values in the current row, or the insert row.
1625     * The updateXXX() methods do not update the underlying database, instead
1626     * the updateRow() or insertRow() methods are called to update the
1627     * database.
1628     *
1629     * @param columnIndex the first column is 1, the second is 2, ...
1630     * @param x the new column value
1631     *
1632     * @exception SQLException if a database-access error occurs
1633     */

1634    public synchronized void updateString(int columnIndex, String JavaDoc x)
1635        throws SQLException JavaDoc {
1636        if (!onInsertRow) {
1637            if (!doingUpdates) {
1638                doingUpdates = true;
1639                syncUpdate();
1640            }
1641
1642            updater.setString(columnIndex, x);
1643        } else {
1644            inserter.setString(columnIndex, x);
1645
1646            if (x == null) {
1647                this.thisRow[columnIndex - 1] = null;
1648            } else {
1649                if (getCharConverter() != null) {
1650                    try {
1651                        this.thisRow[columnIndex - 1] = StringUtils.getBytes(x,
1652                                this.charConverter, this.charEncoding);
1653                    } catch (UnsupportedEncodingException JavaDoc uEE) {
1654                        throw new SQLException JavaDoc(
1655                            "Unsupported character encoding '"
1656                            + this.charEncoding + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1657                    }
1658                } else {
1659                    this.thisRow[columnIndex - 1] = x.getBytes();
1660                }
1661            }
1662        }
1663    }
1664
1665    /**
1666     * JDBC 2.0 Update a column with a String value. The updateXXX() methods
1667     * are used to update column values in the current row, or the insert row.
1668     * The updateXXX() methods do not update the underlying database, instead
1669     * the updateRow() or insertRow() methods are called to update the
1670     * database.
1671     *
1672     * @param columnName the name of the column
1673     * @param x the new column value
1674     *
1675     * @exception SQLException if a database-access error occurs
1676     */

1677    public synchronized void updateString(String JavaDoc columnName, String JavaDoc x)
1678        throws SQLException JavaDoc {
1679        updateString(findColumn(columnName), x);
1680    }
1681
1682    /**
1683     * JDBC 2.0 Update a column with a Time value. The updateXXX() methods are
1684     * used to update column values in the current row, or the insert row. The
1685     * updateXXX() methods do not update the underlying database, instead the
1686     * updateRow() or insertRow() methods are called to update the database.
1687     *
1688     * @param columnIndex the first column is 1, the second is 2, ...
1689     * @param x the new column value
1690     *
1691     * @exception SQLException if a database-access error occurs
1692     */

1693    public synchronized void updateTime(int columnIndex, java.sql.Time JavaDoc x)
1694        throws SQLException JavaDoc {
1695        if (!onInsertRow) {
1696            if (!doingUpdates) {
1697                doingUpdates = true;
1698                syncUpdate();
1699            }
1700
1701            updater.setTime(columnIndex, x);
1702        } else {
1703            inserter.setTime(columnIndex, x);
1704
1705            this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex
1706                    - 1);
1707        }
1708    }
1709
1710    /**
1711     * JDBC 2.0 Update a column with a Time value. The updateXXX() methods are
1712     * used to update column values in the current row, or the insert row. The
1713     * updateXXX() methods do not update the underlying database, instead the
1714     * updateRow() or insertRow() methods are called to update the database.
1715     *
1716     * @param columnName the name of the column
1717     * @param x the new column value
1718     *
1719     * @exception SQLException if a database-access error occurs
1720     */

1721    public synchronized void updateTime(String JavaDoc columnName, java.sql.Time JavaDoc x)
1722        throws SQLException JavaDoc {
1723        updateTime(findColumn(columnName), x);
1724    }
1725
1726    /**
1727     * JDBC 2.0 Update a column with a Timestamp value. The updateXXX()
1728     * methods are used to update column values in the current row, or the
1729     * insert row. The updateXXX() methods do not update the underlying
1730     * database, instead the updateRow() or insertRow() methods are called to
1731     * update the database.
1732     *
1733     * @param columnIndex the first column is 1, the second is 2, ...
1734     * @param x the new column value
1735     *
1736     * @exception SQLException if a database-access error occurs
1737     */

1738    public synchronized void updateTimestamp(int columnIndex,
1739        java.sql.Timestamp JavaDoc x) throws SQLException JavaDoc {
1740        if (!onInsertRow) {
1741            if (!doingUpdates) {
1742                doingUpdates = true;
1743                syncUpdate();
1744            }
1745
1746            updater.setTimestamp(columnIndex, x);
1747        } else {
1748            inserter.setTimestamp(columnIndex, x);
1749
1750            this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex
1751                    - 1);
1752        }
1753    }
1754
1755    /**
1756     * JDBC 2.0 Update a column with a Timestamp value. The updateXXX()
1757     * methods are used to update column values in the current row, or the
1758     * insert row. The updateXXX() methods do not update the underlying
1759     * database, instead the updateRow() or insertRow() methods are called to
1760     * update the database.
1761     *
1762     * @param columnName the name of the column
1763     * @param x the new column value
1764     *
1765     * @exception SQLException if a database-access error occurs
1766     */

1767    public synchronized void updateTimestamp(String JavaDoc columnName,
1768        java.sql.Timestamp JavaDoc x) throws SQLException JavaDoc {
1769        updateTimestamp(findColumn(columnName), x);
1770    }
1771
1772    /**
1773     * Sets the concurrency type of this result set
1774     *
1775     * @param concurrencyFlag the type of concurrency that this ResultSet
1776     * should support.
1777     */

1778    protected void setResultSetConcurrency(int concurrencyFlag) {
1779        super.setResultSetConcurrency(concurrencyFlag);
1780
1781        //
1782
// FIXME: Issue warning when asked for updateable result set, but result set is not
1783
// updatable
1784
//
1785
//if ((concurrencyFlag == CONCUR_UPDATABLE) && !isUpdatable()) {
1786
//java.sql.SQLWarning warning = new java.sql.SQLWarning(
1787
//NotUpdatable.NOT_UPDATEABLE_MESSAGE);
1788
//}
1789
}
1790
1791    protected void checkRowPos() throws SQLException JavaDoc {
1792        // don't use RowData's idea of
1793
// row bounds when we're doing
1794
// inserts...
1795
if (!this.onInsertRow) {
1796            super.checkRowPos();
1797        }
1798    }
1799
1800    /**
1801     * Figure out whether or not this ResultSet is updateable, and if so,
1802     * generate the PreparedStatements to support updates.
1803     *
1804     * @throws SQLException DOCUMENT ME!
1805     * @throws NotUpdatable DOCUMENT ME!
1806     */

1807    protected void generateStatements() throws SQLException JavaDoc {
1808        if (!isUpdatable) {
1809            this.doingUpdates = false;
1810            this.onInsertRow = false;
1811            
1812            throw new NotUpdatable();
1813        }
1814
1815        String JavaDoc quotedId = getQuotedIdChar();
1816
1817        this.tableName = null;
1818
1819        if (fields[0].getOriginalTableName() != null) {
1820            StringBuffer JavaDoc tableNameBuffer = new StringBuffer JavaDoc();
1821
1822            String JavaDoc databaseName = fields[0].getDatabaseName();
1823
1824            if ((databaseName != null) && (databaseName.length() > 0)) {
1825                tableNameBuffer.append(quotedId);
1826                tableNameBuffer.append(databaseName);
1827                tableNameBuffer.append(quotedId);
1828                tableNameBuffer.append('.');
1829            }
1830
1831            tableNameBuffer.append(quotedId);
1832            tableNameBuffer.append(fields[0].getOriginalTableName());
1833            tableNameBuffer.append(quotedId);
1834
1835            this.tableName = tableNameBuffer.toString();
1836        } else {
1837            StringBuffer JavaDoc tableNameBuffer = new StringBuffer JavaDoc();
1838
1839            tableNameBuffer.append(quotedId);
1840            tableNameBuffer.append(fields[0].getTableName());
1841            tableNameBuffer.append(quotedId);
1842
1843            this.tableName = tableNameBuffer.toString();
1844        }
1845
1846        primaryKeyIndicies = new ArrayList JavaDoc();
1847
1848        StringBuffer JavaDoc fieldValues = new StringBuffer JavaDoc();
1849        StringBuffer JavaDoc keyValues = new StringBuffer JavaDoc();
1850        StringBuffer JavaDoc columnNames = new StringBuffer JavaDoc();
1851        StringBuffer JavaDoc insertPlaceHolders = new StringBuffer JavaDoc();
1852        boolean firstTime = true;
1853        boolean keysFirstTime = true;
1854
1855        for (int i = 0; i < fields.length; i++) {
1856            String JavaDoc originalColumnName = fields[i].getOriginalName();
1857            String JavaDoc columnName = null;
1858
1859            if (this.connection.getIO().hasLongColumnInfo()
1860                    && (originalColumnName != null)
1861                    && (originalColumnName.length() > 0)) {
1862                columnName = originalColumnName;
1863            } else {
1864                columnName = fields[i].getName();
1865            }
1866
1867            if (fields[i].isPrimaryKey()) {
1868                primaryKeyIndicies.add(new Integer JavaDoc(i));
1869
1870                if (!keysFirstTime) {
1871                    keyValues.append(" AND ");
1872                } else {
1873                    keysFirstTime = false;
1874                }
1875
1876                keyValues.append(quotedId);
1877                keyValues.append(columnName);
1878                keyValues.append(quotedId);
1879                keyValues.append("=?");
1880            }
1881
1882            if (firstTime) {
1883                firstTime = false;
1884                fieldValues.append("SET ");
1885            } else {
1886                fieldValues.append(",");
1887                columnNames.append(",");
1888                insertPlaceHolders.append(",");
1889            }
1890
1891            insertPlaceHolders.append("?");
1892
1893            columnNames.append(quotedId);
1894            columnNames.append(columnName);
1895            columnNames.append(quotedId);
1896
1897            fieldValues.append(quotedId);
1898            fieldValues.append(columnName);
1899            fieldValues.append(quotedId);
1900            fieldValues.append("=?");
1901        }
1902
1903        updateSQL = "UPDATE " + this.tableName + " " + fieldValues.toString()
1904            + " WHERE " + keyValues.toString();
1905        insertSQL = "INSERT INTO " + this.tableName + " ("
1906            + columnNames.toString() + ") VALUES ("
1907            + insertPlaceHolders.toString() + ")";
1908        refreshSQL = "SELECT " + columnNames.toString() + " FROM " + tableName
1909            + " WHERE " + keyValues.toString();
1910        deleteSQL = "DELETE FROM " + this.tableName + " WHERE "
1911            + keyValues.toString();
1912    }
1913
1914    boolean isUpdatable() {
1915        return this.isUpdatable;
1916    }
1917
1918    /**
1919     * Reset UPDATE prepared statement to value in current row. This_Row MUST
1920     * point to current, valid row.
1921     *
1922     * @throws SQLException DOCUMENT ME!
1923     */

1924    void syncUpdate() throws SQLException JavaDoc {
1925        if (updater == null) {
1926            if (updateSQL == null) {
1927                generateStatements();
1928            }
1929
1930            updater = (com.mysql.jdbc.PreparedStatement) connection
1931                .prepareStatement(updateSQL);
1932            
1933            if (updater.getMaxRows() != 0) {
1934                updater.setMaxRows(0);
1935            }
1936        }
1937
1938        int numFields = fields.length;
1939        updater.clearParameters();
1940
1941        for (int i = 0; i < numFields; i++) {
1942            if (thisRow[i] != null) {
1943                updater.setBytes(i + 1, thisRow[i]);
1944            } else {
1945                updater.setNull(i + 1, 0);
1946            }
1947        }
1948
1949        int numKeys = primaryKeyIndicies.size();
1950
1951        if (numKeys == 1) {
1952            int index = ((Integer JavaDoc) primaryKeyIndicies.get(0)).intValue();
1953            byte[] keyData = thisRow[index];
1954            updater.setBytes(numFields + 1, keyData);
1955        } else {
1956            for (int i = 0; i < numKeys; i++) {
1957                byte[] currentVal = thisRow[((Integer JavaDoc) primaryKeyIndicies.get(i))
1958                    .intValue()];
1959
1960                if (currentVal != null) {
1961                    updater.setBytes(numFields + i + 1, currentVal);
1962                } else {
1963                    updater.setNull(numFields + i + 1, 0);
1964                }
1965            }
1966        }
1967    }
1968
1969    private boolean initializedCharConverter = false;
1970    
1971    private synchronized SingleByteCharsetConverter getCharConverter()
1972        throws SQLException JavaDoc {
1973        if (!this.initializedCharConverter) {
1974            this.initializedCharConverter = true;
1975            
1976            if (this.connection.useUnicode()) {
1977                this.charEncoding = connection.getEncoding();
1978                this.charConverter = this.connection.getCharsetConverter(this.charEncoding);
1979            }
1980        }
1981
1982        return this.charConverter;
1983    }
1984
1985    private synchronized String JavaDoc getQuotedIdChar() throws SQLException JavaDoc {
1986        if (this.quotedIdChar == null) {
1987            boolean useQuotedIdentifiers = connection.supportsQuotedIdentifiers();
1988
1989            if (useQuotedIdentifiers) {
1990                java.sql.DatabaseMetaData JavaDoc dbmd = connection.getMetaData();
1991                this.quotedIdChar = dbmd.getIdentifierQuoteString();
1992            } else {
1993                this.quotedIdChar = "";
1994            }
1995        }
1996
1997        return this.quotedIdChar;
1998    }
1999
2000    /**
2001     * DOCUMENT ME!
2002     *
2003     * @param field
2004     *
2005     * @return String
2006     */

2007    private String JavaDoc getTableName(Field field) {
2008        String JavaDoc originalTableName = field.getOriginalTableName();
2009
2010        if ((originalTableName != null) && (originalTableName.length() > 0)) {
2011            return originalTableName;
2012        } else {
2013            return field.getTableName();
2014        }
2015    }
2016
2017    /**
2018     * Is this ResultSet updateable?
2019     *
2020     * @return DOCUMENT ME!
2021     *
2022     * @throws SQLException DOCUMENT ME!
2023     */

2024    private boolean checkUpdatability() throws SQLException JavaDoc {
2025        String JavaDoc tableName = null;
2026        String JavaDoc catalogName = null;
2027
2028        int primaryKeyCount = 0;
2029
2030        if (fields.length > 0) {
2031            
2032            tableName = fields[0].getOriginalTableName();
2033            catalogName = fields[0].getDatabaseName();
2034            
2035            if (tableName == null) {
2036                tableName = fields[0].getTableName();
2037                catalogName = this.catalog;
2038            }
2039
2040            if (fields[0].isPrimaryKey()) {
2041                primaryKeyCount++;
2042            }
2043
2044            //
2045
// References only one table?
2046
//
2047
for (int i = 1; i < fields.length; i++) {
2048                String JavaDoc otherTableName = fields[i].getOriginalTableName();
2049                
2050                String JavaDoc otherCatalogName = fields[i].getDatabaseName();
2051                
2052                if (otherTableName == null) {
2053                    otherTableName = fields[i].getTableName();
2054                    otherCatalogName = this.catalog;
2055                }
2056                
2057                // Can't have more than one table
2058
if ((tableName == null)
2059                        || !otherTableName.equals(tableName)) {
2060                    return false;
2061                }
2062
2063                // Can't reference more than one database
2064
if ((catalogName == null) || !otherCatalogName.equals(catalogName)) {
2065                    return false;
2066                }
2067                
2068                if (fields[i].isPrimaryKey()) {
2069                    primaryKeyCount++;
2070                }
2071            }
2072
2073            if ((tableName == null) || (tableName.length() == 0)) {
2074                return false;
2075            }
2076        } else {
2077            return false;
2078        }
2079
2080        //
2081
// Must have at least one primary key
2082
//
2083
if (primaryKeyCount == 0) {
2084            return false;
2085        }
2086
2087        // We can only do this if we know that there is a currently
2088
// selected database, or if we're talking to a > 4.1 version
2089
// of MySQL server (as it returns database names in field
2090
// info)
2091
//
2092
if ((this.catalog == null) || (this.catalog.length() == 0)) {
2093            this.catalog = fields[0].getDatabaseName();
2094
2095            if ((this.catalog == null) || (this.catalog.length() == 0)) {
2096                throw new SQLException JavaDoc(
2097                "Can not create updatable result sets when there is no currently selected database"
2098                + " and MySQL server version < 4.1", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2099            }
2100        }
2101
2102        if (this.connection.useStrictUpdates()) {
2103            java.sql.DatabaseMetaData JavaDoc dbmd = this.connection.getMetaData();
2104
2105            java.sql.ResultSet JavaDoc rs = null;
2106            HashMap JavaDoc primaryKeyNames = new HashMap JavaDoc();
2107
2108            try {
2109                rs = dbmd.getPrimaryKeys(catalogName, null, tableName);
2110
2111                while (rs.next()) {
2112                    String JavaDoc keyName = rs.getString(4);
2113                    keyName = keyName.toUpperCase();
2114                    primaryKeyNames.put(keyName, keyName);
2115                }
2116            } finally {
2117                if (rs != null) {
2118                    try {
2119                        rs.close();
2120                    } catch (Exception JavaDoc ex) {
2121                        AssertionFailedException.shouldNotHappen(ex);
2122                    }
2123
2124                    rs = null;
2125                }
2126            }
2127
2128            if (primaryKeyNames.size() == 0) {
2129                return false; // we can't update tables w/o keys
2130
}
2131
2132            //
2133
// Contains all primary keys?
2134
//
2135
for (int i = 0; i < fields.length; i++) {
2136                if (fields[i].isPrimaryKey()) {
2137                    String JavaDoc columnNameUC = fields[i].getName().toUpperCase();
2138
2139                    if (primaryKeyNames.remove(columnNameUC) == null) {
2140                        // try original name
2141
String JavaDoc originalName = fields[i].getOriginalName();
2142
2143                        if (originalName != null) {
2144                            if (primaryKeyNames.remove(
2145                                        originalName.toUpperCase()) == null) {
2146                                // we don't know about this key, so give up :(
2147
return false;
2148                            }
2149                        }
2150                    }
2151                }
2152            }
2153
2154            return primaryKeyNames.isEmpty();
2155        }
2156
2157        return true;
2158    }
2159
2160    private synchronized void extractDefaultValues() throws SQLException JavaDoc {
2161        java.sql.DatabaseMetaData JavaDoc dbmd = this.connection.getMetaData();
2162
2163        java.sql.ResultSet JavaDoc columnsResultSet = null;
2164
2165        try {
2166            String JavaDoc unquotedTableName = this.tableName;
2167
2168            if (unquotedTableName.startsWith(this.quotedIdChar)) {
2169                unquotedTableName = unquotedTableName.substring(1);
2170            }
2171
2172            if (unquotedTableName.endsWith(this.quotedIdChar)) {
2173                unquotedTableName = unquotedTableName.substring(0,
2174                        unquotedTableName.length() - 1);
2175            }
2176
2177            columnsResultSet = dbmd.getColumns(this.catalog, null,
2178                    unquotedTableName, "%");
2179
2180            HashMap JavaDoc columnNameToDefaultValueMap = new HashMap JavaDoc(this.fields.length /* at least this big... */);
2181
2182            while (columnsResultSet.next()) {
2183                String JavaDoc columnName = columnsResultSet.getString("COLUMN_NAME");
2184                byte[] defaultValue = columnsResultSet.getBytes("COLUMN_DEF");
2185
2186                columnNameToDefaultValueMap.put(columnName, defaultValue);
2187            }
2188
2189            int numFields = this.fields.length;
2190
2191            this.defaultColumnValue = new byte[numFields][];
2192
2193            for (int i = 0; i < numFields; i++) {
2194                String JavaDoc tableName = this.fields[i].getOriginalName();
2195
2196                if ((tableName == null) || (tableName.length() == 0)) {
2197                    tableName = this.fields[i].getName();
2198                }
2199
2200                if (tableName != null) {
2201                    byte[] defaultVal = (byte[]) columnNameToDefaultValueMap
2202                        .get(tableName);
2203
2204                    this.defaultColumnValue[i] = defaultVal;
2205                }
2206            }
2207        } finally {
2208            if (columnsResultSet != null) {
2209                columnsResultSet.close();
2210
2211                columnsResultSet = null;
2212            }
2213        }
2214    }
2215
2216    private void resetInserter() throws SQLException JavaDoc {
2217        inserter.clearParameters();
2218
2219        for (int i = 0; i < fields.length; i++) {
2220            inserter.setNull(i + 1, 0);
2221        }
2222    }
2223}
2224
Popular Tags