EMMA Coverage Report (generated Mon Jul 24 20:22:52 CDT 2006)
[all classes][com.mysql.jdbc]

COVERAGE SUMMARY FOR SOURCE FILE [UpdatableResultSet.java]

nameclass, %method, %block, %line, %
UpdatableResultSet.java100% (1/1)49%  (39/80)63%  (1784/2825)63%  (406.4/645)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class UpdatableResultSet100% (1/1)49%  (39/80)63%  (1784/2825)63%  (406.4/645)
UpdatableResultSet (long, long, Connection, Statement): void 0%   (0/1)0%   (0/42)0%   (0/14)
afterLast (): void 0%   (0/1)0%   (0/3)0%   (0/2)
isFirst (): boolean 0%   (0/1)0%   (0/3)0%   (0/1)
isLast (): boolean 0%   (0/1)0%   (0/3)0%   (0/1)
isUpdatable (): boolean 0%   (0/1)0%   (0/3)0%   (0/1)
prev (): boolean 0%   (0/1)0%   (0/3)0%   (0/1)
previous (): boolean 0%   (0/1)0%   (0/3)0%   (0/1)
relative (int): boolean 0%   (0/1)0%   (0/4)0%   (0/1)
rowDeleted (): boolean 0%   (0/1)0%   (0/4)0%   (0/1)
rowInserted (): boolean 0%   (0/1)0%   (0/4)0%   (0/1)
rowUpdated (): boolean 0%   (0/1)0%   (0/4)0%   (0/1)
updateAsciiStream (String, InputStream, int): void 0%   (0/1)0%   (0/8)0%   (0/2)
updateAsciiStream (int, InputStream, int): void 0%   (0/1)0%   (0/32)0%   (0/8)
updateBigDecimal (String, BigDecimal): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateBigDecimal (int, BigDecimal): void 0%   (0/1)0%   (0/42)0%   (0/10)
updateBlob (String, Blob): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateBlob (int, Blob): void 0%   (0/1)0%   (0/40)0%   (0/10)
updateBoolean (String, boolean): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateBoolean (int, boolean): void 0%   (0/1)0%   (0/35)0%   (0/8)
updateByte (String, byte): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateBytes (String, byte []): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateBytes (int, byte []): void 0%   (0/1)0%   (0/30)0%   (0/8)
updateCharacterStream (String, Reader, int): void 0%   (0/1)0%   (0/8)0%   (0/2)
updateDate (String, Date): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateDate (int, Date): void 0%   (0/1)0%   (0/35)0%   (0/8)
updateDouble (String, double): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateDouble (int, double): void 0%   (0/1)0%   (0/35)0%   (0/8)
updateFloat (String, float): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateFloat (int, float): void 0%   (0/1)0%   (0/35)0%   (0/8)
updateLong (String, long): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateLong (int, long): void 0%   (0/1)0%   (0/35)0%   (0/8)
updateNull (String): void 0%   (0/1)0%   (0/6)0%   (0/2)
updateNull (int): void 0%   (0/1)0%   (0/30)0%   (0/8)
updateObject (String, Object, int): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateObject (int, Object, int): void 0%   (0/1)0%   (0/35)0%   (0/8)
updateShort (String, short): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateShort (int, short): void 0%   (0/1)0%   (0/35)0%   (0/8)
updateTime (String, Time): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateTime (int, Time): void 0%   (0/1)0%   (0/35)0%   (0/8)
updateTimestamp (String, Timestamp): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateTimestamp (int, Timestamp): void 0%   (0/1)0%   (0/35)0%   (0/8)
realClose (boolean): void 100% (1/1)39%  (43/111)59%  (19/32)
updateObject (int, Object): void 100% (1/1)51%  (18/35)75%  (6/8)
deleteRow (): void 100% (1/1)55%  (96/174)67%  (22.8/34)
updateString (int, String): void 100% (1/1)58%  (38/65)85%  (11/13)
updateByte (int, byte): void 100% (1/1)60%  (21/35)50%  (4/8)
updateClob (int, Clob): void 100% (1/1)73%  (11/15)75%  (3/4)
refreshRow (): void 100% (1/1)75%  (177/236)77%  (41.4/54)
moveToCurrentRow (): void 100% (1/1)80%  (16/20)86%  (6/7)
checkUpdatability (): void 100% (1/1)81%  (207/257)75%  (52.4/70)
updateBinaryStream (int, InputStream, int): void 100% (1/1)81%  (34/42)90%  (9/10)
updateCharacterStream (int, Reader, int): void 100% (1/1)81%  (34/42)90%  (9/10)
updateRow (): void 100% (1/1)82%  (18/22)88%  (7/8)
getConcurrency (): int 100% (1/1)86%  (6/7)86%  (0.9/1)
getQuotedIdChar (): String 100% (1/1)88%  (21/24)86%  (6/7)
syncUpdate (): void 100% (1/1)93%  (122/131)95%  (20/21)
insertRow (): void 100% (1/1)94%  (67/71)94%  (15/16)
extractDefaultValues (): void 100% (1/1)96%  (94/98)98%  (22.4/23)
generateStatements (): void 100% (1/1)100% (355/356)100% (67/67)
<static initializer> 100% (1/1)100% (4/4)100% (1/1)
UpdatableResultSet (String, Field [], RowData, Connection, Statement): void 100% (1/1)100% (43/43)100% (14/14)
absolute (int): boolean 100% (1/1)100% (4/4)100% (1/1)
beforeFirst (): void 100% (1/1)100% (3/3)100% (2/2)
cancelRowUpdates (): void 100% (1/1)100% (12/12)100% (5/5)
checkRowPos (): void 100% (1/1)100% (8/8)100% (4/4)
first (): boolean 100% (1/1)100% (3/3)100% (1/1)
getCharConverter (): SingleByteCharsetConverter 100% (1/1)100% (25/25)100% (6/6)
isAfterLast (): boolean 100% (1/1)100% (3/3)100% (1/1)
isBeforeFirst (): boolean 100% (1/1)100% (3/3)100% (1/1)
last (): boolean 100% (1/1)100% (3/3)100% (1/1)
moveToInsertRow (): void 100% (1/1)100% (199/199)100% (29/29)
next (): boolean 100% (1/1)100% (3/3)100% (1/1)
resetInserter (): void 100% (1/1)100% (20/20)100% (4/4)
setResultSetConcurrency (int): void 100% (1/1)100% (4/4)100% (2/2)
stripBinaryPrefix (byte []): byte [] 100% (1/1)100% (5/5)100% (1/1)
updateBinaryStream (String, InputStream, int): void 100% (1/1)100% (8/8)100% (2/2)
updateInt (String, int): void 100% (1/1)100% (7/7)100% (2/2)
updateInt (int, int): void 100% (1/1)100% (35/35)100% (8/8)
updateObject (String, Object): void 100% (1/1)100% (7/7)100% (2/2)
updateString (String, String): void 100% (1/1)100% (7/7)100% (2/2)

1/*
2 Copyright (C) 2002-2004 MySQL AB
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of version 2 of the GNU General Public License as 
6 published by the Free Software Foundation.
7 
8 There are special exceptions to the terms and conditions of the GPL 
9 as it is applied to this software. View the full text of the 
10 exception in file EXCEPTIONS-CONNECTOR-J in the directory of this 
11 software distribution.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 
22 
23 
24 */
25package com.mysql.jdbc;
26 
27import com.mysql.jdbc.profiler.ProfileEventSink;
28import com.mysql.jdbc.profiler.ProfilerEvent;
29 
30import java.math.BigDecimal;
31 
32import java.sql.SQLException;
33 
34import java.util.ArrayList;
35import java.util.HashMap;
36import java.util.List;
37 
38/**
39 * A result set that is updatable.
40 * 
41 * @author Mark Matthews
42 */
43public class UpdatableResultSet extends ResultSet {
44        /** Marker for 'stream' data when doing INSERT rows */
45        private final static byte[] STREAM_DATA_MARKER = "** STREAM DATA **" //$NON-NLS-1$
46        .getBytes();
47 
48        private SingleByteCharsetConverter charConverter;
49 
50        private String charEncoding;
51 
52        /** What is the default value for the column? */
53        private byte[][] defaultColumnValue;
54 
55        /** PreparedStatement used to delete data */
56        private com.mysql.jdbc.PreparedStatement deleter = null;
57 
58        private String deleteSQL = null;
59 
60        private boolean initializedCharConverter = false;
61 
62        /** PreparedStatement used to insert data */
63        private com.mysql.jdbc.PreparedStatement inserter = null;
64 
65        private String insertSQL = null;
66 
67        /** Is this result set updateable? */
68        private boolean isUpdatable = false;
69 
70        /** List of primary keys */
71        private List primaryKeyIndicies = null;
72 
73        private String qualifiedAndQuotedTableName;
74 
75        private String quotedIdChar = null;
76 
77        /** PreparedStatement used to refresh data */
78        private com.mysql.jdbc.PreparedStatement refresher;
79 
80        private String refreshSQL = null;
81 
82        /** The binary data for the 'current' row */
83        private Object[] savedCurrentRow;
84 
85        private String tableOnlyName;
86 
87        /** PreparedStatement used to delete data */
88        private com.mysql.jdbc.PreparedStatement updater = null;
89 
90        /** SQL for in-place modifcation */
91        private String updateSQL = null;
92 
93        /**
94         * Create a result set for an executeUpdate statement.
95         * 
96         * @param updateCount
97         *            the number of rows affected by the update
98         * @param updateID
99         *            the autoincrement value (if any)
100         * @param conn
101         *            DOCUMENT ME!
102         * @param creatorStmt
103         *            DOCUMENT ME!
104         * 
105         * @throws SQLException
106         *             DOCUMENT ME!
107         */
108        public UpdatableResultSet(long updateCount, long updateID, Connection conn,
109                        Statement creatorStmt) throws SQLException {
110                super(updateCount, updateID, conn, creatorStmt);
111                checkUpdatability();
112        }
113 
114        /**
115         * Creates a new ResultSet object.
116         * 
117         * @param catalog
118         *            the database in use when we were created
119         * @param fields
120         *            an array of Field objects (basically, the ResultSet MetaData)
121         * @param tuples
122         *            actual row data
123         * @param conn
124         *            the Connection that created us.
125         * @param creatorStmt
126         *            DOCUMENT ME!
127         * 
128         * @throws SQLException
129         *             DOCUMENT ME!
130         */
131        public UpdatableResultSet(String catalog, Field[] fields, RowData tuples,
132                        Connection conn, Statement creatorStmt) throws SQLException {
133                super(catalog, fields, tuples, conn, creatorStmt);
134                checkUpdatability();
135        }
136 
137        /**
138         * JDBC 2.0
139         * 
140         * <p>
141         * Move to an absolute row number in the result set.
142         * </p>
143         * 
144         * <p>
145         * If row is positive, moves to an absolute row with respect to the
146         * beginning of the result set. The first row is row 1, the second is row 2,
147         * etc.
148         * </p>
149         * 
150         * <p>
151         * If row is negative, moves to an absolute row position with respect to the
152         * end of result set. For example, calling absolute(-1) positions the cursor
153         * on the last row, absolute(-2) indicates the next-to-last row, etc.
154         * </p>
155         * 
156         * <p>
157         * An attempt to position the cursor beyond the first/last row in the result
158         * set, leaves the cursor before/after the first/last row, respectively.
159         * </p>
160         * 
161         * <p>
162         * Note: Calling absolute(1) is the same as calling first(). Calling
163         * absolute(-1) is the same as calling last().
164         * </p>
165         * 
166         * @param row
167         *            DOCUMENT ME!
168         * 
169         * @return true if on the result set, false if off.
170         * 
171         * @exception SQLException
172         *                if a database-access error occurs, or row is 0, or result
173         *                set type is TYPE_FORWARD_ONLY.
174         */
175        public synchronized boolean absolute(int row) throws SQLException {
176                return super.absolute(row);
177        }
178 
179        /**
180         * JDBC 2.0
181         * 
182         * <p>
183         * Moves to the end of the result set, just after the last row. Has no
184         * effect if the result set contains no rows.
185         * </p>
186         * 
187         * @exception SQLException
188         *                if a database-access error occurs, or result set type is
189         *                TYPE_FORWARD_ONLY.
190         */
191        public synchronized void afterLast() throws SQLException {
192                super.afterLast();
193        }
194 
195        /**
196         * JDBC 2.0
197         * 
198         * <p>
199         * Moves to the front of the result set, just before the first row. Has no
200         * effect if the result set contains no rows.
201         * </p>
202         * 
203         * @exception SQLException
204         *                if a database-access error occurs, or result set type is
205         *                TYPE_FORWARD_ONLY
206         */
207        public synchronized void beforeFirst() throws SQLException {
208                super.beforeFirst();
209        }
210 
211        /**
212         * JDBC 2.0 The cancelRowUpdates() method may be called after calling an
213         * updateXXX() method(s) and before calling updateRow() to rollback the
214         * updates made to a row. If no updates have been made or updateRow() has
215         * already been called, then this method has no effect.
216         * 
217         * @exception SQLException
218         *                if a database-access error occurs, or if called when on
219         *                the insert row.
220         */
221        public synchronized void cancelRowUpdates() throws SQLException {
222                checkClosed();
223 
224                if (this.doingUpdates) {
225                        this.doingUpdates = false;
226                        this.updater.clearParameters();
227                }
228        }
229 
230        /*
231         * (non-Javadoc)
232         * 
233         * @see com.mysql.jdbc.ResultSet#checkRowPos()
234         */
235        protected void checkRowPos() throws SQLException {
236                checkClosed();
237 
238                if (!this.onInsertRow) {
239                        super.checkRowPos();
240                }
241        }
242 
243        /**
244         * Is this ResultSet updateable?
245         * 
246         * @throws SQLException
247         *             DOCUMENT ME!
248         */
249        private void checkUpdatability() throws SQLException {
250                String singleTableName = null;
251                String catalogName = null;
252 
253                int primaryKeyCount = 0;
254 
255                if (this.fields.length > 0) {
256                        singleTableName = this.fields[0].getOriginalTableName();
257                        catalogName = this.fields[0].getDatabaseName();
258 
259                        if (singleTableName == null) {
260                                singleTableName = this.fields[0].getTableName();
261                                catalogName = this.catalog;
262                        }
263 
264                        if (this.fields[0].isPrimaryKey()) {
265                                primaryKeyCount++;
266                        }
267 
268                        //
269                        // References only one table?
270                        //
271                        for (int i = 1; i < this.fields.length; i++) {
272                                String otherTableName = this.fields[i].getOriginalTableName();
273                                String otherCatalogName = this.fields[i].getDatabaseName();
274 
275                                if (otherTableName == null) {
276                                        otherTableName = this.fields[i].getTableName();
277                                        otherCatalogName = this.catalog;
278                                }
279 
280                                if ((singleTableName == null)
281                                                || !otherTableName.equals(singleTableName)) {
282                                        this.isUpdatable = false;
283 
284                                        return;
285                                }
286 
287                                // Can't reference more than one database
288                                if ((catalogName == null)
289                                                || !otherCatalogName.equals(catalogName)) {
290                                        this.isUpdatable = false;
291 
292                                        return;
293                                }
294 
295                                if (this.fields[i].isPrimaryKey()) {
296                                        primaryKeyCount++;
297                                }
298                        }
299 
300                        if ((singleTableName == null) || (singleTableName.length() == 0)) {
301                                this.isUpdatable = false;
302 
303                                return;
304                        }
305                } else {
306                        this.isUpdatable = false;
307 
308                        return;
309                }
310 
311                // 
312                // Must have at least one primary key
313                //
314                if (primaryKeyCount == 0) {
315                        this.isUpdatable = false;
316 
317                        return;
318                }
319 
320                // We can only do this if we know that there is a currently
321                // selected database, or if we're talking to a > 4.1 version
322                // of MySQL server (as it returns database names in field
323                // info)
324                //
325                if ((this.catalog == null) || (this.catalog.length() == 0)) {
326                        this.catalog = this.fields[0].getDatabaseName();
327 
328                        if ((this.catalog == null) || (this.catalog.length() == 0)) {
329                                throw SQLError.createSQLException(Messages
330                                                .getString("UpdatableResultSet.43") //$NON-NLS-1$
331                                                , SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ //$NON-NLS-2$
332                        }
333                }
334 
335                if (this.connection.getStrictUpdates()) {
336                        java.sql.DatabaseMetaData dbmd = this.connection.getMetaData();
337 
338                        java.sql.ResultSet rs = null;
339                        HashMap primaryKeyNames = new HashMap();
340 
341                        try {
342                                rs = dbmd.getPrimaryKeys(catalogName, null, singleTableName);
343 
344                                while (rs.next()) {
345                                        String keyName = rs.getString(4);
346                                        keyName = keyName.toUpperCase();
347                                        primaryKeyNames.put(keyName, keyName);
348                                }
349                        } finally {
350                                if (rs != null) {
351                                        try {
352                                                rs.close();
353                                        } catch (Exception ex) {
354                                                AssertionFailedException.shouldNotHappen(ex);
355                                        }
356 
357                                        rs = null;
358                                }
359                        }
360 
361                        if (primaryKeyNames.size() == 0) {
362                                this.isUpdatable = false;
363 
364                                return; // we can't update tables w/o keys
365                        }
366 
367                        //
368                        // Contains all primary keys?
369                        //
370                        for (int i = 0; i < this.fields.length; i++) {
371                                if (this.fields[i].isPrimaryKey()) {
372                                        String columnNameUC = this.fields[i].getName()
373                                                        .toUpperCase();
374 
375                                        if (primaryKeyNames.remove(columnNameUC) == null) {
376                                                // try original name
377                                                String originalName = this.fields[i].getOriginalName();
378 
379                                                if (originalName != null) {
380                                                        if (primaryKeyNames.remove(originalName
381                                                                        .toUpperCase()) == null) {
382                                                                // we don't know about this key, so give up :(
383                                                                this.isUpdatable = false;
384 
385                                                                return;
386                                                        }
387                                                }
388                                        }
389                                }
390                        }
391 
392                        this.isUpdatable = primaryKeyNames.isEmpty();
393 
394                        return;
395                }
396 
397                this.isUpdatable = true;
398 
399                return;
400        }
401 
402        /**
403         * JDBC 2.0 Delete the current row from the result set and the underlying
404         * database. Cannot be called when on the insert row.
405         * 
406         * @exception SQLException
407         *                if a database-access error occurs, or if called when on
408         *                the insert row.
409         * @throws SQLException
410         *             if the ResultSet is not updatable or some other error occurs
411         */
412        public synchronized void deleteRow() throws SQLException {
413                checkClosed();
414 
415                if (!this.isUpdatable) {
416                        throw new NotUpdatable();
417                }
418 
419                if (this.onInsertRow) {
420                        throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.1")); //$NON-NLS-1$
421                } else if (this.rowData.size() == 0) {
422                        throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.2")); //$NON-NLS-1$
423                } else if (isBeforeFirst()) {
424                        throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.3")); //$NON-NLS-1$
425                } else if (isAfterLast()) {
426                        throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.4")); //$NON-NLS-1$
427                }
428 
429                if (this.deleter == null) {
430                        if (this.deleteSQL == null) {
431                                generateStatements();
432                        }
433 
434                        this.deleter = this.connection
435                                        .clientPrepareStatement(this.deleteSQL);
436                }
437 
438                this.deleter.clearParameters();
439 
440                String characterEncoding = null;
441 
442                if (this.connection.getUseUnicode()) {
443                        characterEncoding = this.connection.getEncoding();
444                }
445 
446                //
447                // FIXME: Use internal routines where possible for character
448                // conversion!
449                try {
450                        int numKeys = this.primaryKeyIndicies.size();
451 
452                        if (numKeys == 1) {
453                                int index = ((Integer) this.primaryKeyIndicies.get(0))
454                                                .intValue();
455                                String currentVal = ((characterEncoding == null) ? new String(
456                                                (byte[]) this.thisRow[index]) : new String(
457                                                (byte[]) this.thisRow[index], characterEncoding));
458                                this.deleter.setString(1, currentVal);
459                        } else {
460                                for (int i = 0; i < numKeys; i++) {
461                                        int index = ((Integer) this.primaryKeyIndicies.get(i))
462                                                        .intValue();
463                                        String currentVal = ((characterEncoding == null) ? new String(
464                                                        (byte[]) this.thisRow[index])
465                                                        : new String((byte[]) this.thisRow[index],
466                                                                        characterEncoding));
467                                        this.deleter.setString(i + 1, currentVal);
468                                }
469                        }
470 
471                        this.deleter.executeUpdate();
472                        this.rowData.removeRow(this.rowData.getCurrentRowNumber());
473                } catch (java.io.UnsupportedEncodingException encodingEx) {
474                        throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.39", //$NON-NLS-1$
475                                        new Object[] { this.charEncoding }) //$NON-NLS-1$
476                                        , SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ //$NON-NLS-2$
477                }
478        }
479 
480        private synchronized void extractDefaultValues() throws SQLException {
481                java.sql.DatabaseMetaData dbmd = this.connection.getMetaData();
482 
483                java.sql.ResultSet columnsResultSet = null;
484 
485                try {
486                        columnsResultSet = dbmd.getColumns(this.catalog, null,
487                                        this.tableOnlyName, "%"); //$NON-NLS-1$
488 
489                        HashMap columnNameToDefaultValueMap = new HashMap(
490                                        this.fields.length /* at least this big... */);
491 
492                        while (columnsResultSet.next()) {
493                                String columnName = columnsResultSet.getString("COLUMN_NAME"); //$NON-NLS-1$
494                                byte[] defaultValue = columnsResultSet.getBytes("COLUMN_DEF"); //$NON-NLS-1$
495 
496                                columnNameToDefaultValueMap.put(columnName, defaultValue);
497                        }
498 
499                        int numFields = this.fields.length;
500 
501                        this.defaultColumnValue = new byte[numFields][];
502 
503                        for (int i = 0; i < numFields; i++) {
504                                String defValTableName = this.fields[i].getOriginalName();
505 
506                                if ((defValTableName == null)
507                                                || (defValTableName.length() == 0)) {
508                                        defValTableName = this.fields[i].getName();
509                                }
510 
511                                if (defValTableName != null) {
512                                        byte[] defaultVal = (byte[]) columnNameToDefaultValueMap
513                                                        .get(defValTableName);
514 
515                                        this.defaultColumnValue[i] = defaultVal;
516                                }
517                        }
518                } finally {
519                        if (columnsResultSet != null) {
520                                columnsResultSet.close();
521 
522                                columnsResultSet = null;
523                        }
524                }
525        }
526 
527        /**
528         * JDBC 2.0
529         * 
530         * <p>
531         * Moves to the first row in the result set.
532         * </p>
533         * 
534         * @return true if on a valid row, false if no rows in the result set.
535         * 
536         * @exception SQLException
537         *                if a database-access error occurs, or result set type is
538         *                TYPE_FORWARD_ONLY.
539         */
540        public synchronized boolean first() throws SQLException {
541                return super.first();
542        }
543 
544        /**
545         * Figure out whether or not this ResultSet is updateable, and if so,
546         * generate the PreparedStatements to support updates.
547         * 
548         * @throws SQLException
549         *             DOCUMENT ME!
550         * @throws NotUpdatable
551         *             DOCUMENT ME!
552         */
553        protected synchronized void generateStatements() throws SQLException {
554                if (!this.isUpdatable) {
555                        this.doingUpdates = false;
556                        this.onInsertRow = false;
557 
558                        throw new NotUpdatable();
559                }
560 
561                String quotedId = getQuotedIdChar();
562 
563                if (this.fields[0].getOriginalTableName() != null) {
564                        StringBuffer tableNameBuffer = new StringBuffer();
565 
566                        String databaseName = this.fields[0].getDatabaseName();
567 
568                        if ((databaseName != null) && (databaseName.length() > 0)) {
569                                tableNameBuffer.append(quotedId);
570                                tableNameBuffer.append(databaseName);
571                                tableNameBuffer.append(quotedId);
572                                tableNameBuffer.append('.');
573                        }
574 
575                        this.tableOnlyName = this.fields[0].getOriginalTableName();
576 
577                        tableNameBuffer.append(quotedId);
578                        tableNameBuffer.append(this.tableOnlyName);
579                        tableNameBuffer.append(quotedId);
580 
581                        this.qualifiedAndQuotedTableName = tableNameBuffer.toString();
582                } else {
583                        StringBuffer tableNameBuffer = new StringBuffer();
584 
585                        this.tableOnlyName = this.fields[0].getTableName();
586 
587                        tableNameBuffer.append(quotedId);
588                        tableNameBuffer.append(this.tableOnlyName);
589                        tableNameBuffer.append(quotedId);
590 
591                        this.qualifiedAndQuotedTableName = tableNameBuffer.toString();
592                }
593 
594                this.primaryKeyIndicies = new ArrayList();
595 
596                StringBuffer fieldValues = new StringBuffer();
597                StringBuffer keyValues = new StringBuffer();
598                StringBuffer columnNames = new StringBuffer();
599                StringBuffer insertPlaceHolders = new StringBuffer();
600                boolean firstTime = true;
601                boolean keysFirstTime = true;
602 
603                String equalsStr = this.connection.versionMeetsMinimum(3, 23, 0) ? "<=>"
604                                : "=";
605 
606                for (int i = 0; i < this.fields.length; i++) {
607                        String originalColumnName = this.fields[i].getOriginalName();
608                        String columnName = null;
609 
610                        if (this.connection.getIO().hasLongColumnInfo()
611                                        && (originalColumnName != null)
612                                        && (originalColumnName.length() > 0)) {
613                                columnName = originalColumnName;
614                        } else {
615                                columnName = this.fields[i].getName();
616                        }
617 
618                        if (this.fields[i].isPrimaryKey()) {
619                                this.primaryKeyIndicies.add(new Integer(i));
620 
621                                if (!keysFirstTime) {
622                                        keyValues.append(" AND "); //$NON-NLS-1$
623                                } else {
624                                        keysFirstTime = false;
625                                }
626 
627                                keyValues.append(quotedId);
628                                keyValues.append(columnName);
629                                keyValues.append(quotedId);
630                                keyValues.append(equalsStr);
631                                keyValues.append("?"); //$NON-NLS-1$
632                        }
633 
634                        if (firstTime) {
635                                firstTime = false;
636                                fieldValues.append("SET "); //$NON-NLS-1$
637                        } else {
638                                fieldValues.append(","); //$NON-NLS-1$
639                                columnNames.append(","); //$NON-NLS-1$
640                                insertPlaceHolders.append(","); //$NON-NLS-1$
641                        }
642 
643                        insertPlaceHolders.append("?"); //$NON-NLS-1$
644 
645                        columnNames.append(quotedId);
646                        columnNames.append(columnName);
647                        columnNames.append(quotedId);
648 
649                        fieldValues.append(quotedId);
650                        fieldValues.append(columnName);
651                        fieldValues.append(quotedId);
652                        fieldValues.append("=?"); //$NON-NLS-1$
653                }
654 
655                this.updateSQL = "UPDATE " + this.qualifiedAndQuotedTableName + " " //$NON-NLS-1$ //$NON-NLS-2$
656                                + fieldValues.toString() //$NON-NLS-1$ //$NON-NLS-2$
657                                + " WHERE " + keyValues.toString(); //$NON-NLS-1$
658                this.insertSQL = "INSERT INTO " + this.qualifiedAndQuotedTableName //$NON-NLS-1$
659                                + " (" + columnNames.toString() //$NON-NLS-1$ //$NON-NLS-2$
660                                + ") VALUES (" + insertPlaceHolders.toString() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
661                this.refreshSQL = "SELECT " + columnNames.toString() + " FROM " //$NON-NLS-1$ //$NON-NLS-2$
662                                + this.qualifiedAndQuotedTableName //$NON-NLS-1$ //$NON-NLS-2$
663                                + " WHERE " + keyValues.toString(); //$NON-NLS-1$
664                this.deleteSQL = "DELETE FROM " + this.qualifiedAndQuotedTableName //$NON-NLS-1$
665                                + " WHERE " //$NON-NLS-1$ //$NON-NLS-2$
666                                + keyValues.toString();
667        }
668 
669        private synchronized SingleByteCharsetConverter getCharConverter()
670                        throws SQLException {
671                if (!this.initializedCharConverter) {
672                        this.initializedCharConverter = true;
673 
674                        if (this.connection.getUseUnicode()) {
675                                this.charEncoding = connection.getEncoding();
676                                this.charConverter = this.connection
677                                                .getCharsetConverter(this.charEncoding);
678                        }
679                }
680 
681                return this.charConverter;
682        }
683 
684        /**
685         * JDBC 2.0 Return the concurrency of this result set. The concurrency used
686         * is determined by the statement that created the result set.
687         * 
688         * @return the concurrency type, CONCUR_READ_ONLY, etc.
689         * 
690         * @exception SQLException
691         *                if a database-access error occurs
692         */
693        public int getConcurrency() throws SQLException {
694                return (this.isUpdatable ? CONCUR_UPDATABLE : CONCUR_READ_ONLY);
695        }
696 
697        private synchronized String getQuotedIdChar() throws SQLException {
698                if (this.quotedIdChar == null) {
699                        boolean useQuotedIdentifiers = this.connection
700                                        .supportsQuotedIdentifiers();
701 
702                        if (useQuotedIdentifiers) {
703                                java.sql.DatabaseMetaData dbmd = this.connection.getMetaData();
704                                this.quotedIdChar = dbmd.getIdentifierQuoteString();
705                        } else {
706                                this.quotedIdChar = ""; //$NON-NLS-1$
707                        }
708                }
709 
710                return this.quotedIdChar;
711        }
712 
713        /**
714         * JDBC 2.0 Insert the contents of the insert row into the result set and
715         * the database. Must be on the insert row when this method is called.
716         * 
717         * @exception SQLException
718         *                if a database-access error occurs, if called when not on
719         *                the insert row, or if all non-nullable columns in the
720         *                insert row have not been given a value
721         */
722        public synchronized void insertRow() throws SQLException {
723                checkClosed();
724 
725                if (!this.onInsertRow) {
726                        throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.7")); //$NON-NLS-1$
727                }
728 
729                this.inserter.executeUpdate();
730 
731                long autoIncrementId = this.inserter.getLastInsertID();
732                int numFields = this.fields.length;
733                byte[][] newRow = new byte[numFields][];
734 
735                for (int i = 0; i < numFields; i++) {
736                        if (this.inserter.isNull(i)) {
737                                newRow[i] = null;
738                        } else {
739                                newRow[i] = this.inserter.getBytesRepresentation(i);
740                        }
741 
742                        //
743                        // WARN: This non-variant only holds if MySQL never allows more
744                        // than one auto-increment key (which is the way it is _today_)
745                        //
746                        if (this.fields[i].isAutoIncrement() && autoIncrementId > 0) {
747                                newRow[i] = String.valueOf(autoIncrementId).getBytes();
748                        }
749                }
750 
751                this.rowData.addRow(newRow);
752                resetInserter();
753        }
754 
755        /**
756         * JDBC 2.0
757         * 
758         * <p>
759         * Determine if the cursor is after the last row in the result set.
760         * </p>
761         * 
762         * @return true if after the last row, false otherwise. Returns false when
763         *         the result set contains no rows.
764         * 
765         * @exception SQLException
766         *                if a database-access error occurs.
767         */
768        public synchronized boolean isAfterLast() throws SQLException {
769                return super.isAfterLast();
770        }
771 
772        /**
773         * JDBC 2.0
774         * 
775         * <p>
776         * Determine if the cursor is before the first row in the result set.
777         * </p>
778         * 
779         * @return true if before the first row, false otherwise. Returns false when
780         *         the result set contains no rows.
781         * 
782         * @exception SQLException
783         *                if a database-access error occurs.
784         */
785        public synchronized boolean isBeforeFirst() throws SQLException {
786                return super.isBeforeFirst();
787        }
788 
789        /**
790         * JDBC 2.0
791         * 
792         * <p>
793         * Determine if the cursor is on the first row of the result set.
794         * </p>
795         * 
796         * @return true if on the first row, false otherwise.
797         * 
798         * @exception SQLException
799         *                if a database-access error occurs.
800         */
801        public synchronized boolean isFirst() throws SQLException {
802                return super.isFirst();
803        }
804 
805        /**
806         * JDBC 2.0
807         * 
808         * <p>
809         * Determine if the cursor is on the last row of the result set. Note:
810         * Calling isLast() may be expensive since the JDBC driver might need to
811         * fetch ahead one row in order to determine whether the current row is the
812         * last row in the result set.
813         * </p>
814         * 
815         * @return true if on the last row, false otherwise.
816         * 
817         * @exception SQLException
818         *                if a database-access error occurs.
819         */
820        public synchronized boolean isLast() throws SQLException {
821                return super.isLast();
822        }
823 
824        boolean isUpdatable() {
825                return this.isUpdatable;
826        }
827 
828        /**
829         * JDBC 2.0
830         * 
831         * <p>
832         * Moves to the last row in the result set.
833         * </p>
834         * 
835         * @return true if on a valid row, false if no rows in the result set.
836         * 
837         * @exception SQLException
838         *                if a database-access error occurs, or result set type is
839         *                TYPE_FORWARD_ONLY.
840         */
841        public synchronized boolean last() throws SQLException {
842                return super.last();
843        }
844 
845        /**
846         * JDBC 2.0 Move the cursor to the remembered cursor position, usually the
847         * current row. Has no effect unless the cursor is on the insert row.
848         * 
849         * @exception SQLException
850         *                if a database-access error occurs, or the result set is
851         *                not updatable
852         * @throws SQLException
853         *             if the ResultSet is not updatable or some other error occurs
854         */
855        public synchronized void moveToCurrentRow() throws SQLException {
856                checkClosed();
857 
858                if (!this.isUpdatable) {
859                        throw new NotUpdatable();
860                }
861 
862                if (this.onInsertRow) {
863                        this.onInsertRow = false;
864                        this.thisRow = this.savedCurrentRow;
865                }
866        }
867 
868        /**
869         * JDBC 2.0 Move to the insert row. The current cursor position is
870         * remembered while the cursor is positioned on the insert row. The insert
871         * row is a special row associated with an updatable result set. It is
872         * essentially a buffer where a new row may be constructed by calling the
873         * updateXXX() methods prior to inserting the row into the result set. Only
874         * the updateXXX(), getXXX(), and insertRow() methods may be called when the
875         * cursor is on the insert row. All of the columns in a result set must be
876         * given a value each time this method is called before calling insertRow().
877         * UpdateXXX()must be called before getXXX() on a column.
878         * 
879         * @exception SQLException
880         *                if a database-access error occurs, or the result set is
881         *                not updatable
882         * @throws NotUpdatable
883         *             DOCUMENT ME!
884         */
885        public synchronized void moveToInsertRow() throws SQLException {
886                checkClosed();
887 
888                if (!this.isUpdatable) {
889                        throw new NotUpdatable();
890                }
891 
892                if (this.inserter == null) {
893                        if (this.insertSQL == null) {
894                                generateStatements();
895                        }
896 
897                        this.inserter = this.connection
898                                        .clientPrepareStatement(this.insertSQL);
899                        extractDefaultValues();
900                        resetInserter();
901                } else {
902                        resetInserter();
903                }
904 
905                int numFields = this.fields.length;
906 
907                this.onInsertRow = true;
908                this.doingUpdates = false;
909                this.savedCurrentRow = this.thisRow;
910                this.thisRow = new byte[numFields][];
911 
912                for (int i = 0; i < numFields; i++) {
913                        if (this.defaultColumnValue[i] != null) {
914                                Field f = this.fields[i];
915 
916                                switch (f.getMysqlType()) {
917                                case MysqlDefs.FIELD_TYPE_DATE:
918                                case MysqlDefs.FIELD_TYPE_DATETIME:
919                                case MysqlDefs.FIELD_TYPE_NEWDATE:
920                                case MysqlDefs.FIELD_TYPE_TIME:
921                                case MysqlDefs.FIELD_TYPE_TIMESTAMP:
922 
923                                        if (this.defaultColumnValue[i].length > 7
924                                                        && this.defaultColumnValue[i][0] == (byte) 'C'
925                                                        && this.defaultColumnValue[i][1] == (byte) 'U'
926                                                        && this.defaultColumnValue[i][2] == (byte) 'R'
927                                                        && this.defaultColumnValue[i][3] == (byte) 'R'
928                                                        && this.defaultColumnValue[i][4] == (byte) 'E'
929                                                        && this.defaultColumnValue[i][5] == (byte) 'N'
930                                                        && this.defaultColumnValue[i][6] == (byte) 'T'
931                                                        && this.defaultColumnValue[i][7] == (byte) '_') {
932                                                this.inserter.setBytesNoEscapeNoQuotes(i + 1,
933                                                                this.defaultColumnValue[i]);
934 
935                                                break;
936                                        }
937                                default:
938                                        this.inserter.setBytes(i + 1, this.defaultColumnValue[i],
939                                                        false, false);
940                                }
941 
942                                // This value _could_ be changed from a getBytes(), so we
943                                // need a copy....
944                                byte[] defaultValueCopy = new byte[this.defaultColumnValue[i].length];
945                                System.arraycopy(defaultColumnValue[i], 0, defaultValueCopy, 0,
946                                                defaultValueCopy.length);
947                                this.thisRow[i] = defaultValueCopy;
948                        } else {
949                                this.inserter.setNull(i + 1, java.sql.Types.NULL);
950                                this.thisRow[i] = null;
951                        }
952                }
953        }
954 
955        // ---------------------------------------------------------------------
956        // Updates
957        // ---------------------------------------------------------------------
958 
959        /**
960         * A ResultSet is initially positioned before its first row, the first call
961         * to next makes the first row the current row; the second call makes the
962         * second row the current row, etc.
963         * 
964         * <p>
965         * If an input stream from the previous row is open, it is implicitly
966         * closed. The ResultSet's warning chain is cleared when a new row is read
967         * </p>
968         * 
969         * @return true if the new current is valid; false if there are no more rows
970         * 
971         * @exception SQLException
972         *                if a database access error occurs
973         */
974        public synchronized boolean next() throws SQLException {
975                return super.next();
976        }
977 
978        /**
979         * The prev method is not part of JDBC, but because of the architecture of
980         * this driver it is possible to move both forward and backward within the
981         * result set.
982         * 
983         * <p>
984         * If an input stream from the previous row is open, it is implicitly
985         * closed. The ResultSet's warning chain is cleared when a new row is read
986         * </p>
987         * 
988         * @return true if the new current is valid; false if there are no more rows
989         * 
990         * @exception SQLException
991         *                if a database access error occurs
992         */
993        public synchronized boolean prev() throws SQLException {
994                return super.prev();
995        }
996 
997        /**
998         * JDBC 2.0
999         * 
1000         * <p>
1001         * Moves to the previous row in the result set.
1002         * </p>
1003         * 
1004         * <p>
1005         * Note: previous() is not the same as relative(-1) since it makes sense to
1006         * call previous() when there is no current row.
1007         * </p>
1008         * 
1009         * @return true if on a valid row, false if off the result set.
1010         * 
1011         * @exception SQLException
1012         *                if a database-access error occurs, or result set type is
1013         *                TYPE_FORWAR_DONLY.
1014         */
1015        public synchronized boolean previous() throws SQLException {
1016                return super.previous();
1017        }
1018 
1019        /**
1020         * Closes this ResultSet, releasing all resources.
1021         * 
1022         * @param calledExplicitly
1023         *            was this called from close()?
1024         * 
1025         * @throws SQLException
1026         *             if an error occurs.
1027         */
1028        protected void realClose(boolean calledExplicitly) throws SQLException {
1029                if (this.isClosed) {
1030                        return;
1031                }
1032                
1033                SQLException sqlEx = null;
1034 
1035                if (this.useUsageAdvisor) {
1036                        if ((this.deleter == null) && (this.inserter == null)
1037                                        && (this.refresher == null) && (this.updater == null)) {
1038                                this.eventSink = ProfileEventSink.getInstance(this.connection);
1039 
1040                                String message = Messages.getString("UpdatableResultSet.34"); //$NON-NLS-1$
1041 
1042                                this.eventSink.consumeEvent(new ProfilerEvent(
1043                                                ProfilerEvent.TYPE_WARN, "", //$NON-NLS-1$
1044                                                (this.owningStatement == null) ? "N/A" //$NON-NLS-1$
1045                                                                : this.owningStatement.currentCatalog, //$NON-NLS-1$
1046                                                this.connectionId,
1047                                                (this.owningStatement == null) ? (-1)
1048                                                                : this.owningStatement.getId(), this.resultId,
1049                                                System.currentTimeMillis(), 0, null,
1050                                                this.pointOfOrigin, message));
1051                        }
1052                }
1053 
1054                try {
1055                        if (this.deleter != null) {
1056                                this.deleter.close();
1057                        }
1058                } catch (SQLException ex) {
1059                        sqlEx = ex;
1060                }
1061 
1062                try {
1063                        if (this.inserter != null) {
1064                                this.inserter.close();
1065                        }
1066                } catch (SQLException ex) {
1067                        sqlEx = ex;
1068                }
1069 
1070                try {
1071                        if (this.refresher != null) {
1072                                this.refresher.close();
1073                        }
1074                } catch (SQLException ex) {
1075                        sqlEx = ex;
1076                }
1077 
1078                try {
1079                        if (this.updater != null) {
1080                                this.updater.close();
1081                        }
1082                } catch (SQLException ex) {
1083                        sqlEx = ex;
1084                }
1085 
1086                super.realClose(calledExplicitly);
1087 
1088                if (sqlEx != null) {
1089                        throw sqlEx;
1090                }
1091        }
1092 
1093        /**
1094         * JDBC 2.0 Refresh the value of the current row with its current value in
1095         * the database. Cannot be called when on the insert row. The refreshRow()
1096         * method provides a way for an application to explicitly tell the JDBC
1097         * driver to refetch a row(s) from the database. An application may want to
1098         * call refreshRow() when caching or prefetching is being done by the JDBC
1099         * driver to fetch the latest value of a row from the database. The JDBC
1100         * driver may actually refresh multiple rows at once if the fetch size is
1101         * greater than one. All values are refetched subject to the transaction
1102         * isolation level and cursor sensitivity. If refreshRow() is called after
1103         * calling updateXXX(), but before calling updateRow() then the updates made
1104         * to the row are lost. Calling refreshRow() frequently will likely slow
1105         * performance.
1106         * 
1107         * @exception SQLException
1108         *                if a database-access error occurs, or if called when on
1109         *                the insert row.
1110         * @throws NotUpdatable
1111         *             DOCUMENT ME!
1112         */
1113        public synchronized void refreshRow() throws SQLException {
1114                checkClosed();
1115 
1116                if (!this.isUpdatable) {
1117                        throw new NotUpdatable();
1118                }
1119 
1120                if (this.onInsertRow) {
1121                        throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.8")); //$NON-NLS-1$
1122                } else if (this.rowData.size() == 0) {
1123                        throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.9")); //$NON-NLS-1$
1124                } else if (isBeforeFirst()) {
1125                        throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.10")); //$NON-NLS-1$
1126                } else if (isAfterLast()) {
1127                        throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.11")); //$NON-NLS-1$
1128                }
1129 
1130                if (this.refresher == null) {
1131                        if (this.refreshSQL == null) {
1132                                generateStatements();
1133                        }
1134 
1135                        this.refresher = this.connection
1136                                        .clientPrepareStatement(this.refreshSQL);
1137                }
1138 
1139                this.refresher.clearParameters();
1140 
1141                int numKeys = this.primaryKeyIndicies.size();
1142 
1143                if (numKeys == 1) {
1144                        byte[] dataFrom = null;
1145                        int index = ((Integer) this.primaryKeyIndicies.get(0)).intValue();
1146 
1147                        if (!this.doingUpdates) {
1148                                dataFrom = (byte[]) this.thisRow[index];
1149                        } else {
1150                                dataFrom = this.updater.getBytesRepresentation(index);
1151 
1152                                // Primary keys not set?
1153                                if (this.updater.isNull(index) || (dataFrom.length == 0)) {
1154                                        dataFrom = (byte[]) this.thisRow[index];
1155                                } else {
1156                                        dataFrom = stripBinaryPrefix(dataFrom);
1157                                }
1158                        }
1159 
1160                        this.refresher.setBytesNoEscape(1, dataFrom);
1161                } else {
1162                        for (int i = 0; i < numKeys; i++) {
1163                                byte[] dataFrom = null;
1164                                int index = ((Integer) this.primaryKeyIndicies.get(i))
1165                                                .intValue();
1166 
1167                                if (!this.doingUpdates) {
1168                                        dataFrom = (byte[]) this.thisRow[index];
1169                                } else {
1170                                        dataFrom = this.updater.getBytesRepresentation(index);
1171 
1172                                        // Primary keys not set?
1173                                        if (this.updater.isNull(index) || (dataFrom.length == 0)) {
1174                                                dataFrom = (byte[]) this.thisRow[index];
1175                                        } else {
1176                                                dataFrom = stripBinaryPrefix(dataFrom);
1177                                        }
1178                                }
1179 
1180                                this.refresher.setBytesNoEscape(i + 1, dataFrom);
1181                        }
1182                }
1183 
1184                java.sql.ResultSet rs = null;
1185 
1186                try {
1187                        rs = this.refresher.executeQuery();
1188 
1189                        int numCols = rs.getMetaData().getColumnCount();
1190 
1191                        if (rs.next()) {
1192                                for (int i = 0; i < numCols; i++) {
1193                                        byte[] val = rs.getBytes(i + 1);
1194 
1195                                        if ((val == null) || rs.wasNull()) {
1196                                                this.thisRow[i] = null;
1197                                        } else {
1198                                                this.thisRow[i] = rs.getBytes(i + 1);
1199                                        }
1200                                }
1201                        } else {
1202                                throw SQLError.createSQLException(Messages
1203                                                .getString("UpdatableResultSet.12"), //$NON-NLS-1$
1204                                                SQLError.SQL_STATE_GENERAL_ERROR); //$NON-NLS-1$
1205                        }
1206                } finally {
1207                        if (rs != null) {
1208                                try {
1209                                        rs.close();
1210                                } catch (SQLException ex) {
1211                                        ; // ignore
1212                                }
1213                        }
1214                }
1215        }
1216 
1217        /**
1218         * JDBC 2.0
1219         * 
1220         * <p>
1221         * Moves a relative number of rows, either positive or negative. Attempting
1222         * to move beyond the first/last row in the result set positions the cursor
1223         * before/after the the first/last row. Calling relative(0) is valid, but
1224         * does not change the cursor position.
1225         * </p>
1226         * 
1227         * <p>
1228         * Note: Calling relative(1) is different than calling next() since is makes
1229         * sense to call next() when there is no current row, for example, when the
1230         * cursor is positioned before the first row or after the last row of the
1231         * result set.
1232         * </p>
1233         * 
1234         * @param rows
1235         *            DOCUMENT ME!
1236         * 
1237         * @return true if on a row, false otherwise.
1238         * 
1239         * @exception SQLException
1240         *                if a database-access error occurs, or there is no current
1241         *                row, or result set type is TYPE_FORWARD_ONLY.
1242         */
1243        public synchronized boolean relative(int rows) throws SQLException {
1244                return super.relative(rows);
1245        }
1246 
1247        private void resetInserter() throws SQLException {
1248                this.inserter.clearParameters();
1249 
1250                for (int i = 0; i < this.fields.length; i++) {
1251                        this.inserter.setNull(i + 1, 0);
1252                }
1253        }
1254 
1255        /**
1256         * JDBC 2.0 Determine if this row has been deleted. A deleted row may leave
1257         * a visible "hole" in a result set. This method can be used to detect holes
1258         * in a result set. The value returned depends on whether or not the result
1259         * set can detect deletions.
1260         * 
1261         * @return true if deleted and deletes are detected
1262         * 
1263         * @exception SQLException
1264         *                if a database-access error occurs
1265         * @throws NotImplemented
1266         *             DOCUMENT ME!
1267         * 
1268         * @see DatabaseMetaData#deletesAreDetected
1269         */
1270        public synchronized boolean rowDeleted() throws SQLException {
1271                throw new NotImplemented();
1272        }
1273 
1274        /**
1275         * JDBC 2.0 Determine if the current row has been inserted. The value
1276         * returned depends on whether or not the result set can detect visible
1277         * inserts.
1278         * 
1279         * @return true if inserted and inserts are detected
1280         * 
1281         * @exception SQLException
1282         *                if a database-access error occurs
1283         * @throws NotImplemented
1284         *             DOCUMENT ME!
1285         * 
1286         * @see DatabaseMetaData#insertsAreDetected
1287         */
1288        public synchronized boolean rowInserted() throws SQLException {
1289                throw new NotImplemented();
1290        }
1291 
1292        /**
1293         * JDBC 2.0 Determine if the current row has been updated. The value
1294         * returned depends on whether or not the result set can detect updates.
1295         * 
1296         * @return true if the row has been visibly updated by the owner or another,
1297         *         and updates are detected
1298         * 
1299         * @exception SQLException
1300         *                if a database-access error occurs
1301         * @throws NotImplemented
1302         *             DOCUMENT ME!
1303         * 
1304         * @see DatabaseMetaData#updatesAreDetected
1305         */
1306        public synchronized boolean rowUpdated() throws SQLException {
1307                throw new NotImplemented();
1308        }
1309 
1310        /**
1311         * Sets the concurrency type of this result set
1312         * 
1313         * @param concurrencyFlag
1314         *            the type of concurrency that this ResultSet should support.
1315         */
1316        protected void setResultSetConcurrency(int concurrencyFlag) {
1317                super.setResultSetConcurrency(concurrencyFlag);
1318 
1319                //
1320                // FIXME: Issue warning when asked for updateable result set, but result
1321                // set is not
1322                // updatable
1323                //
1324                // if ((concurrencyFlag == CONCUR_UPDATABLE) && !isUpdatable()) {
1325                // java.sql.SQLWarning warning = new java.sql.SQLWarning(
1326                // NotUpdatable.NOT_UPDATEABLE_MESSAGE);
1327                // }
1328        }
1329 
1330        private byte[] stripBinaryPrefix(byte[] dataFrom) {
1331                return StringUtils.stripEnclosure(dataFrom, "_binary'", "'");
1332        }
1333 
1334        /**
1335         * Reset UPDATE prepared statement to value in current row. This_Row MUST
1336         * point to current, valid row.
1337         * 
1338         * @throws SQLException
1339         *             DOCUMENT ME!
1340         */
1341        synchronized void syncUpdate() throws SQLException {
1342                if (this.updater == null) {
1343                        if (this.updateSQL == null) {
1344                                generateStatements();
1345                        }
1346 
1347                        this.updater = this.connection
1348                                        .clientPrepareStatement(this.updateSQL);
1349                }
1350 
1351                int numFields = this.fields.length;
1352                this.updater.clearParameters();
1353 
1354                for (int i = 0; i < numFields; i++) {
1355                        if (this.thisRow[i] != null) {
1356                                this.updater.setBytes(i + 1, (byte[]) this.thisRow[i],
1357                                                this.fields[i].isBinary(), false);
1358                        } else {
1359                                this.updater.setNull(i + 1, 0);
1360                        }
1361                }
1362 
1363                int numKeys = this.primaryKeyIndicies.size();
1364 
1365                if (numKeys == 1) {
1366                        int index = ((Integer) this.primaryKeyIndicies.get(0)).intValue();
1367                        byte[] keyData = (byte[]) this.thisRow[index];
1368                        this.updater.setBytes(numFields + 1, keyData, false, false);
1369                } else {
1370                        for (int i = 0; i < numKeys; i++) {
1371                                byte[] currentVal = (byte[]) this.thisRow[((Integer) this.primaryKeyIndicies
1372                                                .get(i)).intValue()];
1373 
1374                                if (currentVal != null) {
1375                                        this.updater.setBytes(numFields + i + 1, currentVal, false,
1376                                                        false);
1377                                } else {
1378                                        this.updater.setNull(numFields + i + 1, 0);
1379                                }
1380                        }
1381                }
1382        }
1383 
1384        /**
1385         * JDBC 2.0 Update a column with an ascii stream value. The updateXXX()
1386         * methods are used to update column values in the current row, or the
1387         * insert row. The updateXXX() methods do not update the underlying
1388         * database, instead the updateRow() or insertRow() methods are called to
1389         * update the database.
1390         * 
1391         * @param columnIndex
1392         *            the first column is 1, the second is 2, ...
1393         * @param x
1394         *            the new column value
1395         * @param length
1396         *            the length of the stream
1397         * 
1398         * @exception SQLException
1399         *                if a database-access error occurs
1400         */
1401        public synchronized void updateAsciiStream(int columnIndex,
1402                        java.io.InputStream x, int length) throws SQLException {
1403                if (!this.onInsertRow) {
1404                        if (!this.doingUpdates) {
1405                                this.doingUpdates = true;
1406                                syncUpdate();
1407                        }
1408 
1409                        this.updater.setAsciiStream(columnIndex, x, length);
1410                } else {
1411                        this.inserter.setAsciiStream(columnIndex, x, length);
1412                        this.thisRow[columnIndex - 1] = STREAM_DATA_MARKER;
1413                }
1414        }
1415 
1416        /**
1417         * JDBC 2.0 Update a column with an ascii stream value. The updateXXX()
1418         * methods are used to update column values in the current row, or the
1419         * insert row. The updateXXX() methods do not update the underlying
1420         * database, instead the updateRow() or insertRow() methods are called to
1421         * update the database.
1422         * 
1423         * @param columnName
1424         *            the name of the column
1425         * @param x
1426         *            the new column value
1427         * @param length
1428         *            of the stream
1429         * 
1430         * @exception SQLException
1431         *                if a database-access error occurs
1432         */
1433        public synchronized void updateAsciiStream(String columnName,
1434                        java.io.InputStream x, int length) throws SQLException {
1435                updateAsciiStream(findColumn(columnName), x, length);
1436        }
1437 
1438        /**
1439         * JDBC 2.0 Update a column with a BigDecimal value. The updateXXX() methods
1440         * are used to update column values in the current row, or the insert row.
1441         * The updateXXX() methods do not update the underlying database, instead
1442         * the updateRow() or insertRow() methods are called to update the database.
1443         * 
1444         * @param columnIndex
1445         *            the first column is 1, the second is 2, ...
1446         * @param x
1447         *            the new column value
1448         * 
1449         * @exception SQLException
1450         *                if a database-access error occurs
1451         */
1452        public synchronized void updateBigDecimal(int columnIndex, BigDecimal x)
1453                        throws SQLException {
1454                if (!this.onInsertRow) {
1455                        if (!this.doingUpdates) {
1456                                this.doingUpdates = true;
1457                                syncUpdate();
1458                        }
1459 
1460                        this.updater.setBigDecimal(columnIndex, x);
1461                } else {
1462                        this.inserter.setBigDecimal(columnIndex, x);
1463 
1464                        if (x == null) {
1465                                this.thisRow[columnIndex - 1] = null;
1466                        } else {
1467                                this.thisRow[columnIndex - 1] = x.toString().getBytes();
1468                        }
1469                }
1470        }
1471 
1472        /**
1473         * JDBC 2.0 Update a column with a BigDecimal value. The updateXXX() methods
1474         * are used to update column values in the current row, or the insert row.
1475         * The updateXXX() methods do not update the underlying database, instead
1476         * the updateRow() or insertRow() methods are called to update the database.
1477         * 
1478         * @param columnName
1479         *            the name of the column
1480         * @param x
1481         *            the new column value
1482         * 
1483         * @exception SQLException
1484         *                if a database-access error occurs
1485         */
1486        public synchronized void updateBigDecimal(String columnName, BigDecimal x)
1487                        throws SQLException {
1488                updateBigDecimal(findColumn(columnName), x);
1489        }
1490 
1491        /**
1492         * JDBC 2.0 Update a column with a binary stream value. The updateXXX()
1493         * methods are used to update column values in the current row, or the
1494         * insert row. The updateXXX() methods do not update the underlying
1495         * database, instead the updateRow() or insertRow() methods are called to
1496         * update the database.
1497         * 
1498         * @param columnIndex
1499         *            the first column is 1, the second is 2, ...
1500         * @param x
1501         *            the new column value
1502         * @param length
1503         *            the length of the stream
1504         * 
1505         * @exception SQLException
1506         *                if a database-access error occurs
1507         */
1508        public synchronized void updateBinaryStream(int columnIndex,
1509                        java.io.InputStream x, int length) throws SQLException {
1510                if (!this.onInsertRow) {
1511                        if (!this.doingUpdates) {
1512                                this.doingUpdates = true;
1513                                syncUpdate();
1514                        }
1515 
1516                        this.updater.setBinaryStream(columnIndex, x, length);
1517                } else {
1518                        this.inserter.setBinaryStream(columnIndex, x, length);
1519 
1520                        if (x == null) {
1521                                this.thisRow[columnIndex - 1] = null;
1522                        } else {
1523                                this.thisRow[columnIndex - 1] = STREAM_DATA_MARKER;
1524                        }
1525                }
1526        }
1527 
1528        /**
1529         * JDBC 2.0 Update a column with a binary stream value. The updateXXX()
1530         * methods are used to update column values in the current row, or the
1531         * insert row. The updateXXX() methods do not update the underlying
1532         * database, instead the updateRow() or insertRow() methods are called to
1533         * update the database.
1534         * 
1535         * @param columnName
1536         *            the name of the column
1537         * @param x
1538         *            the new column value
1539         * @param length
1540         *            of the stream
1541         * 
1542         * @exception SQLException
1543         *                if a database-access error occurs
1544         */
1545        public synchronized void updateBinaryStream(String columnName,
1546                        java.io.InputStream x, int length) throws SQLException {
1547                updateBinaryStream(findColumn(columnName), x, length);
1548        }
1549 
1550        /**
1551         * @see ResultSet#updateBlob(int, Blob)
1552         */
1553        public synchronized void updateBlob(int columnIndex, java.sql.Blob blob)
1554                        throws SQLException {
1555                if (!this.onInsertRow) {
1556                        if (!this.doingUpdates) {
1557                                this.doingUpdates = true;
1558                                syncUpdate();
1559                        }
1560 
1561                        this.updater.setBlob(columnIndex, blob);
1562                } else {
1563                        this.inserter.setBlob(columnIndex, blob);
1564 
1565                        if (blob == null) {
1566                                this.thisRow[columnIndex - 1] = null;
1567                        } else {
1568                                this.thisRow[columnIndex - 1] = STREAM_DATA_MARKER;
1569                        }
1570                }
1571        }
1572 
1573        /**
1574         * @see ResultSet#updateBlob(String, Blob)
1575         */
1576        public synchronized void updateBlob(String columnName, java.sql.Blob blob)
1577                        throws SQLException {
1578                updateBlob(findColumn(columnName), blob);
1579        }
1580 
1581        /**
1582         * JDBC 2.0 Update a column with a boolean value. The updateXXX() methods
1583         * are used to update column values in the current row, or the insert row.
1584         * The updateXXX() methods do not update the underlying database, instead
1585         * the updateRow() or insertRow() methods are called to update the database.
1586         * 
1587         * @param columnIndex
1588         *            the first column is 1, the second is 2, ...
1589         * @param x
1590         *            the new column value
1591         * 
1592         * @exception SQLException
1593         *                if a database-access error occurs
1594         */
1595        public synchronized void updateBoolean(int columnIndex, boolean x)
1596                        throws SQLException {
1597                if (!this.onInsertRow) {
1598                        if (!this.doingUpdates) {
1599                                this.doingUpdates = true;
1600                                syncUpdate();
1601                        }
1602 
1603                        this.updater.setBoolean(columnIndex, x);
1604                } else {
1605                        this.inserter.setBoolean(columnIndex, x);
1606 
1607                        this.thisRow[columnIndex - 1] = this.inserter
1608                                        .getBytesRepresentation(columnIndex - 1);
1609                }
1610        }
1611 
1612        /**
1613         * JDBC 2.0 Update a column with a boolean value. The updateXXX() methods
1614         * are used to update column values in the current row, or the insert row.
1615         * The updateXXX() methods do not update the underlying database, instead
1616         * the updateRow() or insertRow() methods are called to update the database.
1617         * 
1618         * @param columnName
1619         *            the name of the column
1620         * @param x
1621         *            the new column value
1622         * 
1623         * @exception SQLException
1624         *                if a database-access error occurs
1625         */
1626        public synchronized void updateBoolean(String columnName, boolean x)
1627                        throws SQLException {
1628                updateBoolean(findColumn(columnName), x);
1629        }
1630 
1631        /**
1632         * JDBC 2.0 Update a column with a byte value. The updateXXX() methods are
1633         * used to update column values in the current row, or the insert row. The
1634         * updateXXX() methods do not update the underlying database, instead the
1635         * updateRow() or insertRow() methods are called to update the database.
1636         * 
1637         * @param columnIndex
1638         *            the first column is 1, the second is 2, ...
1639         * @param x
1640         *            the new column value
1641         * 
1642         * @exception SQLException
1643         *                if a database-access error occurs
1644         */
1645        public synchronized void updateByte(int columnIndex, byte x)
1646                        throws SQLException {
1647                if (!this.onInsertRow) {
1648                        if (!this.doingUpdates) {
1649                                this.doingUpdates = true;
1650                                syncUpdate();
1651                        }
1652 
1653                        this.updater.setByte(columnIndex, x);
1654                } else {
1655                        this.inserter.setByte(columnIndex, x);
1656 
1657                        this.thisRow[columnIndex - 1] = this.inserter
1658                                        .getBytesRepresentation(columnIndex - 1);
1659                }
1660        }
1661 
1662        /**
1663         * JDBC 2.0 Update a column with a byte value. The updateXXX() methods are
1664         * used to update column values in the current row, or the insert row. The
1665         * updateXXX() methods do not update the underlying database, instead the
1666         * updateRow() or insertRow() methods are called to update the database.
1667         * 
1668         * @param columnName
1669         *            the name of the column
1670         * @param x
1671         *            the new column value
1672         * 
1673         * @exception SQLException
1674         *                if a database-access error occurs
1675         */
1676        public synchronized void updateByte(String columnName, byte x)
1677                        throws SQLException {
1678                updateByte(findColumn(columnName), x);
1679        }
1680 
1681        /**
1682         * JDBC 2.0 Update a column with a byte array value. The updateXXX() methods
1683         * are used to update column values in the current row, or the insert row.
1684         * The updateXXX() methods do not update the underlying database, instead
1685         * the updateRow() or insertRow() methods are called to update the database.
1686         * 
1687         * @param columnIndex
1688         *            the first column is 1, the second is 2, ...
1689         * @param x
1690         *            the new column value
1691         * 
1692         * @exception SQLException
1693         *                if a database-access error occurs
1694         */
1695        public synchronized void updateBytes(int columnIndex, byte[] x)
1696                        throws SQLException {
1697                if (!this.onInsertRow) {
1698                        if (!this.doingUpdates) {
1699                                this.doingUpdates = true;
1700                                syncUpdate();
1701                        }
1702 
1703                        this.updater.setBytes(columnIndex, x);
1704                } else {
1705                        this.inserter.setBytes(columnIndex, x);
1706 
1707                        this.thisRow[columnIndex - 1] = x;
1708                }
1709        }
1710 
1711        /**
1712         * JDBC 2.0 Update a column with a byte array value. The updateXXX() methods
1713         * are used to update column values in the current row, or the insert row.
1714         * The updateXXX() methods do not update the underlying database, instead
1715         * the updateRow() or insertRow() methods are called to update the database.
1716         * 
1717         * @param columnName
1718         *            the name of the column
1719         * @param x
1720         *            the new column value
1721         * 
1722         * @exception SQLException
1723         *                if a database-access error occurs
1724         */
1725        public synchronized void updateBytes(String columnName, byte[] x)
1726                        throws SQLException {
1727                updateBytes(findColumn(columnName), x);
1728        }
1729 
1730        /**
1731         * JDBC 2.0 Update a column with a character stream value. The updateXXX()
1732         * methods are used to update column values in the current row, or the
1733         * insert row. The updateXXX() methods do not update the underlying
1734         * database, instead the updateRow() or insertRow() methods are called to
1735         * update the database.
1736         * 
1737         * @param columnIndex
1738         *            the first column is 1, the second is 2, ...
1739         * @param x
1740         *            the new column value
1741         * @param length
1742         *            the length of the stream
1743         * 
1744         * @exception SQLException
1745         *                if a database-access error occurs
1746         */
1747        public synchronized void updateCharacterStream(int columnIndex,
1748                        java.io.Reader x, int length) throws SQLException {
1749                if (!this.onInsertRow) {
1750                        if (!this.doingUpdates) {
1751                                this.doingUpdates = true;
1752                                syncUpdate();
1753                        }
1754 
1755                        this.updater.setCharacterStream(columnIndex, x, length);
1756                } else {
1757                        this.inserter.setCharacterStream(columnIndex, x, length);
1758 
1759                        if (x == null) {
1760                                this.thisRow[columnIndex - 1] = null;
1761                        } else {
1762                                this.thisRow[columnIndex - 1] = STREAM_DATA_MARKER;
1763                        }
1764                }
1765        }
1766 
1767        /**
1768         * JDBC 2.0 Update a column with a character stream value. The updateXXX()
1769         * methods are used to update column values in the current row, or the
1770         * insert row. The updateXXX() methods do not update the underlying
1771         * database, instead the updateRow() or insertRow() methods are called to
1772         * update the database.
1773         * 
1774         * @param columnName
1775         *            the name of the column
1776         * @param reader
1777         *            the new column value
1778         * @param length
1779         *            of the stream
1780         * 
1781         * @exception SQLException
1782         *                if a database-access error occurs
1783         */
1784        public synchronized void updateCharacterStream(String columnName,
1785                        java.io.Reader reader, int length) throws SQLException {
1786                updateCharacterStream(findColumn(columnName), reader, length);
1787        }
1788 
1789        /**
1790         * @see ResultSet#updateClob(int, Clob)
1791         */
1792        public void updateClob(int columnIndex, java.sql.Clob clob)
1793                        throws SQLException {
1794                if (clob == null) {
1795                        updateNull(columnIndex);
1796                } else {
1797                        updateCharacterStream(columnIndex, clob.getCharacterStream(),
1798                                        (int) clob.length());
1799                }
1800        }
1801 
1802        /**
1803         * JDBC 2.0 Update a column with a Date value. The updateXXX() methods are
1804         * used to update column values in the current row, or the insert row. The
1805         * updateXXX() methods do not update the underlying database, instead the
1806         * updateRow() or insertRow() methods are called to update the database.
1807         * 
1808         * @param columnIndex
1809         *            the first column is 1, the second is 2, ...
1810         * @param x
1811         *            the new column value
1812         * 
1813         * @exception SQLException
1814         *                if a database-access error occurs
1815         */
1816        public synchronized void updateDate(int columnIndex, java.sql.Date x)
1817                        throws SQLException {
1818                if (!this.onInsertRow) {
1819                        if (!this.doingUpdates) {
1820                                this.doingUpdates = true;
1821                                syncUpdate();
1822                        }
1823 
1824                        this.updater.setDate(columnIndex, x);
1825                } else {
1826                        this.inserter.setDate(columnIndex, x);
1827 
1828                        this.thisRow[columnIndex - 1] = this.inserter
1829                                        .getBytesRepresentation(columnIndex - 1);
1830                }
1831        }
1832 
1833        /**
1834         * JDBC 2.0 Update a column with a Date value. The updateXXX() methods are
1835         * used to update column values in the current row, or the insert row. The
1836         * updateXXX() methods do not update the underlying database, instead the
1837         * updateRow() or insertRow() methods are called to update the database.
1838         * 
1839         * @param columnName
1840         *            the name of the column
1841         * @param x
1842         *            the new column value
1843         * 
1844         * @exception SQLException
1845         *                if a database-access error occurs
1846         */
1847        public synchronized void updateDate(String columnName, java.sql.Date x)
1848                        throws SQLException {
1849                updateDate(findColumn(columnName), x);
1850        }
1851 
1852        /**
1853         * JDBC 2.0 Update a column with a Double value. The updateXXX() methods are
1854         * used to update column values in the current row, or the insert row. The
1855         * updateXXX() methods do not update the underlying database, instead the
1856         * updateRow() or insertRow() methods are called to update the database.
1857         * 
1858         * @param columnIndex
1859         *            the first column is 1, the second is 2, ...
1860         * @param x
1861         *            the new column value
1862         * 
1863         * @exception SQLException
1864         *                if a database-access error occurs
1865         */
1866        public synchronized void updateDouble(int columnIndex, double x)
1867                        throws SQLException {
1868                if (!this.onInsertRow) {
1869                        if (!this.doingUpdates) {
1870                                this.doingUpdates = true;
1871                                syncUpdate();
1872                        }
1873 
1874                        this.updater.setDouble(columnIndex, x);
1875                } else {
1876                        this.inserter.setDouble(columnIndex, x);
1877 
1878                        this.thisRow[columnIndex - 1] = this.inserter
1879                                        .getBytesRepresentation(columnIndex - 1);
1880                }
1881        }
1882 
1883        /**
1884         * JDBC 2.0 Update a column with a double value. The updateXXX() methods are
1885         * used to update column values in the current row, or the insert row. The
1886         * updateXXX() methods do not update the underlying database, instead the
1887         * updateRow() or insertRow() methods are called to update the database.
1888         * 
1889         * @param columnName
1890         *            the name of the column
1891         * @param x
1892         *            the new column value
1893         * 
1894         * @exception SQLException
1895         *                if a database-access error occurs
1896         */
1897        public synchronized void updateDouble(String columnName, double x)
1898                        throws SQLException {
1899                updateDouble(findColumn(columnName), x);
1900        }
1901 
1902        /**
1903         * JDBC 2.0 Update a column with a float value. The updateXXX() methods are
1904         * used to update column values in the current row, or the insert row. The
1905         * updateXXX() methods do not update the underlying database, instead the
1906         * updateRow() or insertRow() methods are called to update the database.
1907         * 
1908         * @param columnIndex
1909         *            the first column is 1, the second is 2, ...
1910         * @param x
1911         *            the new column value
1912         * 
1913         * @exception SQLException
1914         *                if a database-access error occurs
1915         */
1916        public synchronized void updateFloat(int columnIndex, float x)
1917                        throws SQLException {
1918                if (!this.onInsertRow) {
1919                        if (!this.doingUpdates) {
1920                                this.doingUpdates = true;
1921                                syncUpdate();
1922                        }
1923 
1924                        this.updater.setFloat(columnIndex, x);
1925                } else {
1926                        this.inserter.setFloat(columnIndex, x);
1927 
1928                        this.thisRow[columnIndex - 1] = this.inserter
1929                                        .getBytesRepresentation(columnIndex - 1);
1930                }
1931        }
1932 
1933        /**
1934         * JDBC 2.0 Update a column with a float value. The updateXXX() methods are
1935         * used to update column values in the current row, or the insert row. The
1936         * updateXXX() methods do not update the underlying database, instead the
1937         * updateRow() or insertRow() methods are called to update the database.
1938         * 
1939         * @param columnName
1940         *            the name of the column
1941         * @param x
1942         *            the new column value
1943         * 
1944         * @exception SQLException
1945         *                if a database-access error occurs
1946         */
1947        public synchronized void updateFloat(String columnName, float x)
1948                        throws SQLException {
1949                updateFloat(findColumn(columnName), x);
1950        }
1951 
1952        /**
1953         * JDBC 2.0 Update a column with an integer value. The updateXXX() methods
1954         * are used to update column values in the current row, or the insert row.
1955         * The updateXXX() methods do not update the underlying database, instead
1956         * the updateRow() or insertRow() methods are called to update the database.
1957         * 
1958         * @param columnIndex
1959         *            the first column is 1, the second is 2, ...
1960         * @param x
1961         *            the new column value
1962         * 
1963         * @exception SQLException
1964         *                if a database-access error occurs
1965         */
1966        public synchronized void updateInt(int columnIndex, int x)
1967                        throws SQLException {
1968                if (!this.onInsertRow) {
1969                        if (!this.doingUpdates) {
1970                                this.doingUpdates = true;
1971                                syncUpdate();
1972                        }
1973 
1974                        this.updater.setInt(columnIndex, x);
1975                } else {
1976                        this.inserter.setInt(columnIndex, x);
1977 
1978                        this.thisRow[columnIndex - 1] = this.inserter
1979                                        .getBytesRepresentation(columnIndex - 1);
1980                }
1981        }
1982 
1983        /**
1984         * JDBC 2.0 Update a column with an integer value. The updateXXX() methods
1985         * are used to update column values in the current row, or the insert row.
1986         * The updateXXX() methods do not update the underlying database, instead
1987         * the updateRow() or insertRow() methods are called to update the database.
1988         * 
1989         * @param columnName
1990         *            the name of the column
1991         * @param x
1992         *            the new column value
1993         * 
1994         * @exception SQLException
1995         *                if a database-access error occurs
1996         */
1997        public synchronized void updateInt(String columnName, int x)
1998                        throws SQLException {
1999                updateInt(findColumn(columnName), x);
2000        }
2001 
2002        /**
2003         * JDBC 2.0 Update a column with a long value. The updateXXX() methods are
2004         * used to update column values in the current row, or the insert row. The
2005         * updateXXX() methods do not update the underlying database, instead the
2006         * updateRow() or insertRow() methods are called to update the database.
2007         * 
2008         * @param columnIndex
2009         *            the first column is 1, the second is 2, ...
2010         * @param x
2011         *            the new column value
2012         * 
2013         * @exception SQLException
2014         *                if a database-access error occurs
2015         */
2016        public synchronized void updateLong(int columnIndex, long x)
2017                        throws SQLException {
2018                if (!this.onInsertRow) {
2019                        if (!this.doingUpdates) {
2020                                this.doingUpdates = true;
2021                                syncUpdate();
2022                        }
2023 
2024                        this.updater.setLong(columnIndex, x);
2025                } else {
2026                        this.inserter.setLong(columnIndex, x);
2027 
2028                        this.thisRow[columnIndex - 1] = this.inserter
2029                                        .getBytesRepresentation(columnIndex - 1);
2030                }
2031        }
2032 
2033        /**
2034         * JDBC 2.0 Update a column with a long value. The updateXXX() methods are
2035         * used to update column values in the current row, or the insert row. The
2036         * updateXXX() methods do not update the underlying database, instead the
2037         * updateRow() or insertRow() methods are called to update the database.
2038         * 
2039         * @param columnName
2040         *            the name of the column
2041         * @param x
2042         *            the new column value
2043         * 
2044         * @exception SQLException
2045         *                if a database-access error occurs
2046         */
2047        public synchronized void updateLong(String columnName, long x)
2048                        throws SQLException {
2049                updateLong(findColumn(columnName), x);
2050        }
2051 
2052        /**
2053         * JDBC 2.0 Give a nullable column a null value. The updateXXX() methods are
2054         * used to update column values in the current row, or the insert row. The
2055         * updateXXX() methods do not update the underlying database, instead the
2056         * updateRow() or insertRow() methods are called to update the database.
2057         * 
2058         * @param columnIndex
2059         *            the first column is 1, the second is 2, ...
2060         * 
2061         * @exception SQLException
2062         *                if a database-access error occurs
2063         */
2064        public synchronized void updateNull(int columnIndex) throws SQLException {
2065                if (!this.onInsertRow) {
2066                        if (!this.doingUpdates) {
2067                                this.doingUpdates = true;
2068                                syncUpdate();
2069                        }
2070 
2071                        this.updater.setNull(columnIndex, 0);
2072                } else {
2073                        this.inserter.setNull(columnIndex, 0);
2074 
2075                        this.thisRow[columnIndex - 1] = null;
2076                }
2077        }
2078 
2079        /**
2080         * JDBC 2.0 Update a column with a null value. The updateXXX() methods are
2081         * used to update column values in the current row, or the insert row. The
2082         * updateXXX() methods do not update the underlying database, instead the
2083         * updateRow() or insertRow() methods are called to update the database.
2084         * 
2085         * @param columnName
2086         *            the name of the column
2087         * 
2088         * @exception SQLException
2089         *                if a database-access error occurs
2090         */
2091        public synchronized void updateNull(String columnName) throws SQLException {
2092                updateNull(findColumn(columnName));
2093        }
2094 
2095        /**
2096         * JDBC 2.0 Update a column with an Object value. The updateXXX() methods
2097         * are used to update column values in the current row, or the insert row.
2098         * The updateXXX() methods do not update the underlying database, instead
2099         * the updateRow() or insertRow() methods are called to update the database.
2100         * 
2101         * @param columnIndex
2102         *            the first column is 1, the second is 2, ...
2103         * @param x
2104         *            the new column value
2105         * 
2106         * @exception SQLException
2107         *                if a database-access error occurs
2108         */
2109        public synchronized void updateObject(int columnIndex, Object x)
2110                        throws SQLException {
2111                if (!this.onInsertRow) {
2112                        if (!this.doingUpdates) {
2113                                this.doingUpdates = true;
2114                                syncUpdate();
2115                        }
2116 
2117                        this.updater.setObject(columnIndex, x);
2118                } else {
2119                        this.inserter.setObject(columnIndex, x);
2120 
2121                        this.thisRow[columnIndex - 1] = this.inserter
2122                                        .getBytesRepresentation(columnIndex - 1);
2123                }
2124        }
2125 
2126        /**
2127         * JDBC 2.0 Update a column with an Object value. The updateXXX() methods
2128         * are used to update column values in the current row, or the insert row.
2129         * The updateXXX() methods do not update the underlying database, instead
2130         * the updateRow() or insertRow() methods are called to update the database.
2131         * 
2132         * @param columnIndex
2133         *            the first column is 1, the second is 2, ...
2134         * @param x
2135         *            the new column value
2136         * @param scale
2137         *            For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
2138         *            this is the number of digits after the decimal. For all other
2139         *            types this value will be ignored.
2140         * 
2141         * @exception SQLException
2142         *                if a database-access error occurs
2143         */
2144        public synchronized void updateObject(int columnIndex, Object x, int scale)
2145                        throws SQLException {
2146                if (!this.onInsertRow) {
2147                        if (!this.doingUpdates) {
2148                                this.doingUpdates = true;
2149                                syncUpdate();
2150                        }
2151 
2152                        this.updater.setObject(columnIndex, x);
2153                } else {
2154                        this.inserter.setObject(columnIndex, x);
2155 
2156                        this.thisRow[columnIndex - 1] = this.inserter
2157                                        .getBytesRepresentation(columnIndex - 1);
2158                }
2159        }
2160 
2161        /**
2162         * JDBC 2.0 Update a column with an Object value. The updateXXX() methods
2163         * are used to update column values in the current row, or the insert row.
2164         * The updateXXX() methods do not update the underlying database, instead
2165         * the updateRow() or insertRow() methods are called to update the database.
2166         * 
2167         * @param columnName
2168         *            the name of the column
2169         * @param x
2170         *            the new column value
2171         * 
2172         * @exception SQLException
2173         *                if a database-access error occurs
2174         */
2175        public synchronized void updateObject(String columnName, Object x)
2176                        throws SQLException {
2177                updateObject(findColumn(columnName), x);
2178        }
2179 
2180        /**
2181         * JDBC 2.0 Update a column with an Object value. The updateXXX() methods
2182         * are used to update column values in the current row, or the insert row.
2183         * The updateXXX() methods do not update the underlying database, instead
2184         * the updateRow() or insertRow() methods are called to update the database.
2185         * 
2186         * @param columnName
2187         *            the name of the column
2188         * @param x
2189         *            the new column value
2190         * @param scale
2191         *            For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
2192         *            this is the number of digits after the decimal. For all other
2193         *            types this value will be ignored.
2194         * 
2195         * @exception SQLException
2196         *                if a database-access error occurs
2197         */
2198        public synchronized void updateObject(String columnName, Object x, int scale)
2199                        throws SQLException {
2200                updateObject(findColumn(columnName), x);
2201        }
2202 
2203        /**
2204         * JDBC 2.0 Update the underlying database with the new contents of the
2205         * current row. Cannot be called when on the insert row.
2206         * 
2207         * @exception SQLException
2208         *                if a database-access error occurs, or if called when on
2209         *                the insert row
2210         * @throws NotUpdatable
2211         *             DOCUMENT ME!
2212         */
2213        public synchronized void updateRow() throws SQLException {
2214                if (!this.isUpdatable) {
2215                        throw new NotUpdatable();
2216                }
2217 
2218                if (this.doingUpdates) {
2219                        this.updater.executeUpdate();
2220                        refreshRow();
2221                        this.doingUpdates = false;
2222                }
2223 
2224                //
2225                // fixes calling updateRow() and then doing more
2226                // updates on same row...
2227                syncUpdate();
2228        }
2229 
2230        /**
2231         * JDBC 2.0 Update a column with a short value. The updateXXX() methods are
2232         * used to update column values in the current row, or the insert row. The
2233         * updateXXX() methods do not update the underlying database, instead the
2234         * updateRow() or insertRow() methods are called to update the database.
2235         * 
2236         * @param columnIndex
2237         *            the first column is 1, the second is 2, ...
2238         * @param x
2239         *            the new column value
2240         * 
2241         * @exception SQLException
2242         *                if a database-access error occurs
2243         */
2244        public synchronized void updateShort(int columnIndex, short x)
2245                        throws SQLException {
2246                if (!this.onInsertRow) {
2247                        if (!this.doingUpdates) {
2248                                this.doingUpdates = true;
2249                                syncUpdate();
2250                        }
2251 
2252                        this.updater.setShort(columnIndex, x);
2253                } else {
2254                        this.inserter.setShort(columnIndex, x);
2255 
2256                        this.thisRow[columnIndex - 1] = this.inserter
2257                                        .getBytesRepresentation(columnIndex - 1);
2258                }
2259        }
2260 
2261        /**
2262         * JDBC 2.0 Update a column with a short value. The updateXXX() methods are
2263         * used to update column values in the current row, or the insert row. The
2264         * updateXXX() methods do not update the underlying database, instead the
2265         * updateRow() or insertRow() methods are called to update the database.
2266         * 
2267         * @param columnName
2268         *            the name of the column
2269         * @param x
2270         *            the new column value
2271         * 
2272         * @exception SQLException
2273         *                if a database-access error occurs
2274         */
2275        public synchronized void updateShort(String columnName, short x)
2276                        throws SQLException {
2277                updateShort(findColumn(columnName), x);
2278        }
2279 
2280        /**
2281         * JDBC 2.0 Update a column with a String value. The updateXXX() methods are
2282         * used to update column values in the current row, or the insert row. The
2283         * updateXXX() methods do not update the underlying database, instead the
2284         * updateRow() or insertRow() methods are called to update the database.
2285         * 
2286         * @param columnIndex
2287         *            the first column is 1, the second is 2, ...
2288         * @param x
2289         *            the new column value
2290         * 
2291         * @exception SQLException
2292         *                if a database-access error occurs
2293         */
2294        public synchronized void updateString(int columnIndex, String x)
2295                        throws SQLException {
2296                checkClosed();
2297                
2298                if (!this.onInsertRow) {
2299                        if (!this.doingUpdates) {
2300                                this.doingUpdates = true;
2301                                syncUpdate();
2302                        }
2303 
2304                        this.updater.setString(columnIndex, x);
2305                } else {
2306                        this.inserter.setString(columnIndex, x);
2307 
2308                        if (x == null) {
2309                                this.thisRow[columnIndex - 1] = null;
2310                        } else {
2311                                if (getCharConverter() != null) {
2312                                        this.thisRow[columnIndex - 1] = StringUtils.getBytes(x,
2313                                                        this.charConverter, this.charEncoding,
2314                                                        this.connection.getServerCharacterEncoding(),
2315                                                        this.connection.parserKnowsUnicode());
2316                                } else {
2317                                        this.thisRow[columnIndex - 1] = x.getBytes();
2318                                }
2319                        }
2320                }
2321        }
2322 
2323        /**
2324         * JDBC 2.0 Update a column with a String value. The updateXXX() methods are
2325         * used to update column values in the current row, or the insert row. The
2326         * updateXXX() methods do not update the underlying database, instead the
2327         * updateRow() or insertRow() methods are called to update the database.
2328         * 
2329         * @param columnName
2330         *            the name of the column
2331         * @param x
2332         *            the new column value
2333         * 
2334         * @exception SQLException
2335         *                if a database-access error occurs
2336         */
2337        public synchronized void updateString(String columnName, String x)
2338                        throws SQLException {
2339                updateString(findColumn(columnName), x);
2340        }
2341 
2342        /**
2343         * JDBC 2.0 Update a column with a Time value. The updateXXX() methods are
2344         * used to update column values in the current row, or the insert row. The
2345         * updateXXX() methods do not update the underlying database, instead the
2346         * updateRow() or insertRow() methods are called to update the database.
2347         * 
2348         * @param columnIndex
2349         *            the first column is 1, the second is 2, ...
2350         * @param x
2351         *            the new column value
2352         * 
2353         * @exception SQLException
2354         *                if a database-access error occurs
2355         */
2356        public synchronized void updateTime(int columnIndex, java.sql.Time x)
2357                        throws SQLException {
2358                if (!this.onInsertRow) {
2359                        if (!this.doingUpdates) {
2360                                this.doingUpdates = true;
2361                                syncUpdate();
2362                        }
2363 
2364                        this.updater.setTime(columnIndex, x);
2365                } else {
2366                        this.inserter.setTime(columnIndex, x);
2367 
2368                        this.thisRow[columnIndex - 1] = this.inserter
2369                                        .getBytesRepresentation(columnIndex - 1);
2370                }
2371        }
2372 
2373        /**
2374         * JDBC 2.0 Update a column with a Time value. The updateXXX() methods are
2375         * used to update column values in the current row, or the insert row. The
2376         * updateXXX() methods do not update the underlying database, instead the
2377         * updateRow() or insertRow() methods are called to update the database.
2378         * 
2379         * @param columnName
2380         *            the name of the column
2381         * @param x
2382         *            the new column value
2383         * 
2384         * @exception SQLException
2385         *                if a database-access error occurs
2386         */
2387        public synchronized void updateTime(String columnName, java.sql.Time x)
2388                        throws SQLException {
2389                updateTime(findColumn(columnName), x);
2390        }
2391 
2392        /**
2393         * JDBC 2.0 Update a column with a Timestamp value. The updateXXX() methods
2394         * are used to update column values in the current row, or the insert row.
2395         * The updateXXX() methods do not update the underlying database, instead
2396         * the updateRow() or insertRow() methods are called to update the database.
2397         * 
2398         * @param columnIndex
2399         *            the first column is 1, the second is 2, ...
2400         * @param x
2401         *            the new column value
2402         * 
2403         * @exception SQLException
2404         *                if a database-access error occurs
2405         */
2406        public synchronized void updateTimestamp(int columnIndex,
2407                        java.sql.Timestamp x) throws SQLException {
2408                if (!this.onInsertRow) {
2409                        if (!this.doingUpdates) {
2410                                this.doingUpdates = true;
2411                                syncUpdate();
2412                        }
2413 
2414                        this.updater.setTimestamp(columnIndex, x);
2415                } else {
2416                        this.inserter.setTimestamp(columnIndex, x);
2417 
2418                        this.thisRow[columnIndex - 1] = this.inserter
2419                                        .getBytesRepresentation(columnIndex - 1);
2420                }
2421        }
2422 
2423        /**
2424         * JDBC 2.0 Update a column with a Timestamp value. The updateXXX() methods
2425         * are used to update column values in the current row, or the insert row.
2426         * The updateXXX() methods do not update the underlying database, instead
2427         * the updateRow() or insertRow() methods are called to update the database.
2428         * 
2429         * @param columnName
2430         *            the name of the column
2431         * @param x
2432         *            the new column value
2433         * 
2434         * @exception SQLException
2435         *                if a database-access error occurs
2436         */
2437        public synchronized void updateTimestamp(String columnName,
2438                        java.sql.Timestamp x) throws SQLException {
2439                updateTimestamp(findColumn(columnName), x);
2440        }
2441}

[all classes][com.mysql.jdbc]
EMMA 2.0.4217 (C) Vladimir Roubtsov