Source Code Cross Referenced for DriverResultSet.java in  » Database-JDBC-Connection-Pool » sequoia-2.10.9 » org » continuent » sequoia » driver » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database JDBC Connection Pool » sequoia 2.10.9 » org.continuent.sequoia.driver 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**
0002:         * Sequoia: Database clustering technology.
0003:         * Copyright (C) 2002-2004 French National Institute For Research In Computer
0004:         * Science And Control (INRIA).
0005:         * Copyright (C) 2005 AmicoSoft, Inc. dba Emic Networks
0006:         * Contact: sequoia@continuent.org
0007:         * 
0008:         * Licensed under the Apache License, Version 2.0 (the "License");
0009:         * you may not use this file except in compliance with the License.
0010:         * You may obtain a copy of the License at
0011:         * 
0012:         * http://www.apache.org/licenses/LICENSE-2.0
0013:         * 
0014:         * Unless required by applicable law or agreed to in writing, software
0015:         * distributed under the License is distributed on an "AS IS" BASIS,
0016:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017:         * See the License for the specific language governing permissions and
0018:         * limitations under the License. 
0019:         *
0020:         * Initial developer(s): Mark Matthews. 
0021:         * Contributor(s): Emmanuel Cecchet, Andre Austin, Marc Wick, Jean-Bernard
0022:         * van Zuylen, Marc Herbert, Edward Archibald, Stephane Giron.
0023:         */package org.continuent.sequoia.driver;
0024:
0025:        import java.io.ByteArrayInputStream;
0026:        import java.io.IOException;
0027:        import java.io.InputStream;
0028:        import java.io.UnsupportedEncodingException;
0029:        import java.math.BigDecimal;
0030:        import java.math.BigInteger;
0031:        import java.net.URL;
0032:        import java.nio.CharBuffer;
0033:        import java.nio.charset.CharacterCodingException;
0034:        import java.nio.charset.Charset;
0035:        import java.sql.Clob;
0036:        import java.sql.PreparedStatement;
0037:        import java.sql.Ref;
0038:        import java.sql.ResultSet;
0039:        import java.sql.SQLException;
0040:        import java.sql.SQLWarning;
0041:        import java.sql.Time;
0042:        import java.sql.Timestamp;
0043:        import java.util.ArrayList;
0044:        import java.util.Calendar;
0045:        import java.util.Hashtable;
0046:
0047:        import org.continuent.sequoia.common.exceptions.NotImplementedException;
0048:        import org.continuent.sequoia.common.exceptions.ProtocolException;
0049:        import org.continuent.sequoia.common.exceptions.driver.DriverSQLException;
0050:        import org.continuent.sequoia.common.exceptions.driver.protocol.BackendDriverException;
0051:        import org.continuent.sequoia.common.protocol.ByteArrayBlob;
0052:        import org.continuent.sequoia.common.protocol.Field;
0053:        import org.continuent.sequoia.common.protocol.SQLDataSerialization;
0054:        import org.continuent.sequoia.common.protocol.StringClob;
0055:        import org.continuent.sequoia.common.protocol.TypeTag;
0056:        import org.continuent.sequoia.common.stream.DriverBufferedInputStream;
0057:
0058:        /**
0059:         * A <code>ResultSet</code> provides access to a table of data generated by
0060:         * executing a Statement. The table rows are retrieved in sequence. Within a row
0061:         * its column values can be accessed in any order.
0062:         * <p>
0063:         * A <code>ResultSet</code> maintains a cursor pointing to its current row of
0064:         * data. Initially the cursor is positioned before the first row. The 'next'
0065:         * method moves the cursor to the next row.
0066:         * <p>
0067:         * The <code>getXXX</code> methods retrieve column values for the current row.
0068:         * You can retrieve values either using the index number of the column, or by
0069:         * using the name of the column. In general using the column index will be more
0070:         * efficient. Columns are numbered from 1.
0071:         * <p>
0072:         * For maximum portability, <code>ResultSet</code> columns within each row
0073:         * should be read in left-to-right order and each column should be read only
0074:         * once.
0075:         * <p>
0076:         * For the <code>getXXX</code> methods, the JDBC driver attempts to convert
0077:         * the underlying data to the specified Java type and returns a suitable Java
0078:         * value. See the JDBC specification for allowable mappings from SQL types to
0079:         * Java types with the <code>ResultSet</code> <code>getXXX</code> methods.
0080:         * <p>
0081:         * Column names used as input to <code>getXXX</code> methods are case
0082:         * insenstive. When performing a <code>getXXX</code> using a column name, if
0083:         * several columns have the same name, then the value of the first matching
0084:         * column will be returned. The column name option is designed to be used when
0085:         * column names are used in the SQL Query. For columns that are NOT explicitly
0086:         * named in the query, it is best to use column numbers. If column names were
0087:         * used there is no way for the programmer to guarentee that they actually refer
0088:         * to the intended columns.
0089:         * <P>
0090:         * A <code>ResultSet</code> is automatically closed by the
0091:         * <code>Statement</code> that generated it when that <code>Statement</code>
0092:         * is closed, re-executed, or is used to retrieve the next result from a
0093:         * sequence of multiple results.
0094:         * <P>
0095:         * The number, types and properties of a ResultSet's columns are provided by the
0096:         * <code>ResultSetMetaData</code> object returned by the
0097:         * <code>getMetaData</code> method.
0098:         * 
0099:         * @see java.sql.ResultSetMetaData
0100:         * @see java.sql.ResultSet
0101:         * @author Mark Matthews <mmatthew@worldserver.com>
0102:         * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
0103:         * @author <a href="mailto:alexander.laamanen@tecnomen.com">Alexander Laamanen
0104:         *         </a>
0105:         * @author <a href="mailto:Nicolas.Modrzyk@inrialpes.fr">Nicolas Modrzyk </a>
0106:         * @author <a href="mailto:jbvanzuylen@transwide.com">Jean-Bernard van Zuylen
0107:         *         </a>
0108:         * @author <a href="mailto:Marc.Herbert@emicnetworks.com">Marc Herbert </a>
0109:         * @author <a href="mailto:ed.archibald@continuent.com">Edward Archibald</a>
0110:         * @author <a href="mailto:stephane.giron@continuent.com">Stephane Giron</a>
0111:         * @version 1.0
0112:         */
0113:        public class DriverResultSet implements  java.sql.ResultSet,
0114:                java.io.Serializable, java.lang.Cloneable {
0115:            private static final long serialVersionUID = 7408879935608629886L;
0116:
0117:            /** Cursor to current row */
0118:            protected int currentRow = -1;
0119:            /** Number of rows */
0120:            protected int nbOfRows = -1;
0121:            /** Number of columns */
0122:            protected int nbOfColumns = -1;
0123:            /** The results */
0124:            protected ArrayList data;
0125:            /** True if there is more data to fetch from the controller */
0126:            private boolean hasMoreData;
0127:            /** The fetch direction (not used yet) */
0128:            protected int fetchDirection = FETCH_FORWARD;
0129:            /** The fetch size */
0130:            protected int fetchSize = 0;
0131:            /** ResultSet cursor name */
0132:            private String cursorName;
0133:
0134:            /** The fields */
0135:            protected Field[] fields;
0136:
0137:            /** Pointers to column-specific de/serializer */
0138:            private SQLDataSerialization.Serializer[] serializers;
0139:
0140:            /** for wasNull() */
0141:            protected boolean wasNullFlag = false;
0142:            /** column name -> index in ResultSet data array */
0143:            protected transient Hashtable lowerNameToIndex = null;
0144:            /** case sensitive column name -> index in ResultSet data array */
0145:            protected transient Hashtable sensitiveNameToIndex = null;
0146:
0147:            /** Type of ResultSet */
0148:            protected int resultSetType = 0;
0149:            /** Concurrency for this ResultSet */
0150:            protected int resultSetConcurrency = 0;
0151:            /** the warning chain */
0152:            protected BackendDriverException warnings = null;
0153:            /** warnings associated to the statement that created us */
0154:            protected SQLWarning statementWarnings = null;
0155:            /** Statement corresponding to this ResultSet, if any (not for metadata) */
0156:            protected transient Statement owningStatement;
0157:            /** The driver connection we were received from. Useful for streaming */
0158:            private final Connection connection;
0159:
0160:            private boolean isClosed = true;
0161:
0162:            /** Statement for deleting rows with Updatable ResultSets * */
0163:            private transient PreparedStatement deleteStatement = null;
0164:            /** Statement for inserting rows with Updatable ResultSets * */
0165:            private transient PreparedStatement insertStatement = null;
0166:            /** Statement for refreshing rows with Updatable ResultSets * */
0167:            private transient PreparedStatement refreshStatement = null;
0168:            /** Statement for updating rows with Updatable ResultSets * */
0169:            private transient PreparedStatement updateStatement = null;
0170:            /** Indicates whether cursor is on the insert row * */
0171:            private transient boolean inserting = false;
0172:            /** Indicates if the current row is being updated * */
0173:            private transient boolean updating = false;
0174:            /** Temporary object for not yet comitted ResultSet updates * */
0175:            private transient Object[] tempRow = null;
0176:            /** Cache the columns forming the primary key * */
0177:            private transient String[] primaryKeyColumns = null;
0178:
0179:            private static final String UPDATEABLE_MESSAGE = "ResultSet not updateable. The "
0180:                    + "query that generated this result set must select only one table, and must "
0181:                    + "select all primary keys from that table. See the JDBC 2.1 API Specification, "
0182:                    + "section 5.6 for more details.";
0183:            /**
0184:             * Hold a reference to the returned stream so we can close it as soon as the
0185:             * application is no more allowed to use it (per the JDBC spec).
0186:             */
0187:            private InputStream currentStream = null;
0188:
0189:            // ---------------------------------------------------------------------
0190:            // Traversal/Positioning
0191:            // ---------------------------------------------------------------------
0192:
0193:            /**
0194:             * A ResultSet is initially positioned before its first row, the first call to
0195:             * next makes the first row the current row; the second call makes the second
0196:             * row the current row, etc.
0197:             * <p>
0198:             * If an input stream from the previous row is open, it is implicitly closed.
0199:             * The ResultSet's warning chain is cleared when a new row is read
0200:             * 
0201:             * @return <code>true</code> if the new current is valid; <code>false</code>
0202:             *         if there are no more rows
0203:             * @exception java.sql.SQLException if a database access error occurs
0204:             */
0205:            public boolean next() throws java.sql.SQLException {
0206:                checkIfClosed();
0207:
0208:                if (inserting) {
0209:                    insertStatement.clearParameters();
0210:                    tempRow = null;
0211:                    inserting = false;
0212:                }
0213:
0214:                if (updating)
0215:                    cancelRowUpdates();
0216:
0217:                if (nbOfRows == 0)
0218:                    return false;
0219:
0220:                if (currentRow + 1 >= nbOfRows) {
0221:                    if (hasMoreData) {
0222:                        // TODO: what happens if user closed this connection? What says JDBC?
0223:                        this .connection.tryFetchNext(cursorName, fetchSize);
0224:                        // no SQLException from controller, so let's receive our new rows
0225:                        try {
0226:                            receiveRows();
0227:                        } catch (IOException ioe) {
0228:                            throw new DriverSQLException(
0229:                                    "I/O Error while fetching new rows:\n"
0230:                                            + ioe.getLocalizedMessage(), ioe);
0231:                        }
0232:                        currentRow = 0;
0233:                        if (data == null) {
0234:                            nbOfRows = 0;
0235:                            return false;
0236:                        } else {
0237:                            nbOfRows = data.size();
0238:                            return true;
0239:                        }
0240:                    }
0241:
0242:                    // force scroll past end
0243:                    currentRow = nbOfRows;
0244:                    return false;
0245:                }
0246:
0247:                clearWarnings();
0248:                currentRow++;
0249:                return true;
0250:            }
0251:
0252:            /**
0253:             * The prev method is not part of JDBC, but because of the architecture of
0254:             * this driver it is possible to move both forward and backward within the
0255:             * result set.
0256:             * <p>
0257:             * If an input stream from the previous row is open, it is implicitly closed.
0258:             * The ResultSet's warning chain is cleared when a new row is read
0259:             * 
0260:             * @return <code>true</code> if the new current is valid; <code>false</code>
0261:             *         if there are no more rows
0262:             * @exception SQLException if a database access error occurs
0263:             */
0264:            public boolean prev() throws SQLException {
0265:                checkIfClosed();
0266:
0267:                if (inserting) {
0268:                    insertStatement.clearParameters();
0269:                    tempRow = null;
0270:                    inserting = false;
0271:                }
0272:
0273:                if (updating)
0274:                    cancelRowUpdates();
0275:
0276:                if (currentRow - 1 >= 0) {
0277:                    currentRow--;
0278:                    return true;
0279:                }
0280:
0281:                return false;
0282:            }
0283:
0284:            /**
0285:             * JDBC 2.0.
0286:             * <p>
0287:             * Determine if the cursor is before the first row in the result set.
0288:             * 
0289:             * @return <code>true</code> if before the first row, <code>false</code>
0290:             *         otherwise. Returns <code>false</code> when the result set
0291:             *         contains no rows.
0292:             * @exception SQLException if a database-access error occurs.
0293:             */
0294:            public boolean isBeforeFirst() throws SQLException {
0295:                checkIfClosed();
0296:                if (nbOfRows == 0)
0297:                    return false;
0298:                else
0299:                    return (currentRow == -1);
0300:            }
0301:
0302:            /**
0303:             * JDBC 2.0
0304:             * <p>
0305:             * Determine if the cursor is after the last row in the result set.
0306:             * 
0307:             * @return <code>true</code> if after the last row, <code>false</code>
0308:             *         otherwise. Returns <code>false</code> when the result set
0309:             *         contains no rows.
0310:             * @exception SQLException if a database-access error occurs.
0311:             */
0312:            public boolean isAfterLast() throws SQLException {
0313:                checkIfClosed();
0314:                if (nbOfRows == 0)
0315:                    return false;
0316:                else
0317:                    return (currentRow >= nbOfRows);
0318:            }
0319:
0320:            /**
0321:             * JDBC 2.0
0322:             * <p>
0323:             * Determine if the cursor is on the first row of the result set.
0324:             * 
0325:             * @return <code>true</code> if on the first row, <code>false</code>
0326:             *         otherwise.
0327:             * @exception SQLException if a database-access error occurs.
0328:             */
0329:            public boolean isFirst() throws SQLException {
0330:                checkIfClosed();
0331:                if (nbOfRows == 0)
0332:                    return false;
0333:                else
0334:                    return (currentRow == 0);
0335:            }
0336:
0337:            /**
0338:             * JDBC 2.0
0339:             * <p>
0340:             * Determine if the cursor is on the last row of the result set. Note: Calling
0341:             * isLast() may be expensive since the JDBC driver might need to fetch ahead
0342:             * one row in order to determine whether the current row is the last row in
0343:             * the result set.
0344:             * 
0345:             * @return <code>true</code> if on the last row, <code>false</code>
0346:             *         otherwise.
0347:             * @exception SQLException if a database-access error occurs.
0348:             */
0349:            public boolean isLast() throws SQLException {
0350:                checkIfClosed();
0351:                if (nbOfRows == 0)
0352:                    return false;
0353:                else
0354:                    return (currentRow == nbOfRows - 1);
0355:            }
0356:
0357:            /**
0358:             * JDBC 2.0
0359:             * <p>
0360:             * Moves to the front of the result set, just before the first row. Has no
0361:             * effect if the result set contains no rows.
0362:             * 
0363:             * @exception SQLException if a database-access error occurs, or result set
0364:             *              type is TYPE_FORWARD_ONLY
0365:             */
0366:            public void beforeFirst() throws SQLException {
0367:                checkIfScrollable();
0368:
0369:                if (inserting) {
0370:                    insertStatement.clearParameters();
0371:                    tempRow = null;
0372:                    inserting = false;
0373:                }
0374:
0375:                if (updating)
0376:                    cancelRowUpdates();
0377:
0378:                currentRow = -1;
0379:            }
0380:
0381:            /**
0382:             * JDBC 2.0
0383:             * <p>
0384:             * Moves to the end of the result set, just after the last row. Has no effect
0385:             * if the result set contains no rows.
0386:             * 
0387:             * @exception SQLException if a database-access error occurs, or result set
0388:             *              type is TYPE_FORWARD_ONLY.
0389:             */
0390:            public void afterLast() throws SQLException {
0391:                checkIfScrollable();
0392:
0393:                if (inserting) {
0394:                    insertStatement.clearParameters();
0395:                    tempRow = null;
0396:                    inserting = false;
0397:                }
0398:
0399:                if (updating)
0400:                    cancelRowUpdates();
0401:
0402:                if (nbOfRows != 0)
0403:                    currentRow = nbOfRows;
0404:            }
0405:
0406:            /**
0407:             * JDBC 2.0
0408:             * <p>
0409:             * Moves to the first row in the result set.
0410:             * 
0411:             * @return <code>true</code> if on a valid row, false if no rows in the
0412:             *         result set.
0413:             * @exception SQLException if a database-access error occurs, or result set
0414:             *              type is TYPE_FORWARD_ONLY.
0415:             */
0416:            public boolean first() throws SQLException {
0417:                checkIfScrollable();
0418:
0419:                if (inserting) {
0420:                    insertStatement.clearParameters();
0421:                    tempRow = null;
0422:                    inserting = false;
0423:                }
0424:
0425:                if (updating)
0426:                    cancelRowUpdates();
0427:
0428:                if (nbOfRows == 0)
0429:                    return false;
0430:
0431:                currentRow = 0;
0432:                return true;
0433:            }
0434:
0435:            /**
0436:             * JDBC 2.0
0437:             * <p>
0438:             * Moves to the last row in the result set.
0439:             * 
0440:             * @return <code>true</code> if on a valid row, false if no rows in the
0441:             *         result set.
0442:             * @exception SQLException if a database-access error occurs, or result set
0443:             *              type is TYPE_FORWARD_ONLY.
0444:             */
0445:            public boolean last() throws SQLException {
0446:                checkIfScrollable();
0447:
0448:                if (inserting) {
0449:                    insertStatement.clearParameters();
0450:                    tempRow = null;
0451:                    inserting = false;
0452:                }
0453:
0454:                if (updating)
0455:                    cancelRowUpdates();
0456:
0457:                if (nbOfRows == 0)
0458:                    return false;
0459:
0460:                currentRow = nbOfRows - 1;
0461:                return true;
0462:            }
0463:
0464:            /**
0465:             * JDBC 2.0
0466:             * <p>
0467:             * Determine the current row number. The first row is number 1, the second
0468:             * number 2, etc.
0469:             * 
0470:             * @return the current row number, else return 0 if there is no current row
0471:             * @exception SQLException if a database-access error occurs.
0472:             */
0473:            public int getRow() throws SQLException {
0474:                checkIfClosed();
0475:                if (currentRow < 0 || currentRow >= nbOfRows || nbOfRows == 0)
0476:                    return 0;
0477:                else
0478:                    return currentRow + 1;
0479:            }
0480:
0481:            /**
0482:             * JDBC 2.0
0483:             * <p>
0484:             * Move to an absolute row number in the result set.
0485:             * <p>
0486:             * If row is positive, moves to an absolute row with respect to the beginning
0487:             * of the result set. The first row is row 1, the second is row 2, etc.
0488:             * <p>
0489:             * If row is negative, moves to an absolute row position with respect to the
0490:             * end of result set. For example, calling absolute(-1) positions the cursor
0491:             * on the last row, absolute(-2) indicates the next-to-last row, etc.
0492:             * <p>
0493:             * An attempt to position the cursor beyond the first/last row in the result
0494:             * set, leaves the cursor before/after the first/last row, respectively.
0495:             * <p>
0496:             * Note: Calling absolute(1) is the same as calling first(). Calling
0497:             * absolute(-1) is the same as calling last().
0498:             * 
0499:             * @param row the row to move to
0500:             * @return <code>true</code> if on the result set, false if off.
0501:             * @exception SQLException if a database-access error occurs, or row is 0, or
0502:             *              result set type is TYPE_FORWARD_ONLY.
0503:             */
0504:            public boolean absolute(int row) throws SQLException {
0505:                checkIfScrollable();
0506:
0507:                if (inserting) {
0508:                    insertStatement.clearParameters();
0509:                    tempRow = null;
0510:                    inserting = false;
0511:                }
0512:
0513:                if (updating)
0514:                    cancelRowUpdates();
0515:
0516:                if (nbOfRows == 0)
0517:                    return false;
0518:
0519:                if (row == 0) {
0520:                    beforeFirst();
0521:                    return false;
0522:                }
0523:
0524:                if (row == 1)
0525:                    return first();
0526:
0527:                if (row == -1)
0528:                    return last();
0529:
0530:                if (row > nbOfRows) {
0531:                    afterLast();
0532:                    return false;
0533:                }
0534:
0535:                if (row < 0) { // adjust to reflect after end of result set
0536:                    int newRowPosition = nbOfRows + row + 1;
0537:
0538:                    if (newRowPosition <= 0) {
0539:                        beforeFirst();
0540:                        return false;
0541:                    }
0542:
0543:                    return absolute(newRowPosition);
0544:                } else {
0545:                    row--; // adjust for index difference
0546:                    currentRow = row;
0547:                    return true;
0548:                }
0549:            }
0550:
0551:            /**
0552:             * JDBC 2.0
0553:             * <p>
0554:             * Moves a relative number of rows, either positive or negative. Attempting to
0555:             * move beyond the first/last row in the result set positions the cursor
0556:             * before/after the the first/last row. Calling relative(0) is valid, but does
0557:             * not change the cursor position.
0558:             * <p>
0559:             * Note: Calling relative(1) is different than calling next() since is makes
0560:             * sense to call next() when there is no current row, for example, when the
0561:             * cursor is positioned before the first row or after the last row of the
0562:             * result set.
0563:             * 
0564:             * @param rows the number of rows
0565:             * @return <code>true</code> if on a row, false otherwise.
0566:             * @exception SQLException if a database-access error occurs, or there is no
0567:             *              current row, or result set type is TYPE_FORWARD_ONLY.
0568:             */
0569:            public boolean relative(int rows) throws SQLException {
0570:                checkIfScrollable();
0571:
0572:                if (inserting) {
0573:                    insertStatement.clearParameters();
0574:                    tempRow = null;
0575:                    inserting = false;
0576:                }
0577:
0578:                if (updating)
0579:                    cancelRowUpdates();
0580:
0581:                if (nbOfRows == 0)
0582:                    return false;
0583:
0584:                return absolute(currentRow + rows + 1);
0585:            }
0586:
0587:            /**
0588:             * JDBC 2.0
0589:             * <p>
0590:             * Moves to the previous row in the result set.
0591:             * <p>
0592:             * Note: previous() is not the same as relative(-1) since it makes sense to
0593:             * call previous() when there is no current row.
0594:             * 
0595:             * @return <code>true</code> if on a valid row, false if off the result set.
0596:             * @exception SQLException if a database-access error occurs, or result set
0597:             *              type is TYPE_FORWAR_DONLY.
0598:             */
0599:            public boolean previous() throws SQLException {
0600:                checkIfScrollable();
0601:                return prev();
0602:            }
0603:
0604:            /**
0605:             * JDBC 2.0 Give a hint as to the direction in which the rows in this result
0606:             * set will be processed. The initial value is determined by the statement
0607:             * that produced the result set. The fetch direction may be changed at any
0608:             * time.
0609:             * 
0610:             * @param direction the fetch direction
0611:             * @exception SQLException if a database-access error occurs, or the result
0612:             *              set type is TYPE_FORWARD_ONLY and direction is not
0613:             *              FETCH_FORWARD. MM.MySQL actually ignores this, because it has
0614:             *              the whole result set anyway, so the direction is immaterial.
0615:             */
0616:            public void setFetchDirection(int direction) throws SQLException {
0617:                if (direction != FETCH_FORWARD && direction != FETCH_REVERSE)
0618:                    throw new SQLException("Illegal value for fetch direction");
0619:
0620:                if (resultSetType == ResultSet.TYPE_FORWARD_ONLY
0621:                        && direction != FETCH_FORWARD)
0622:                    throw new SQLException(
0623:                            "Operation requires a scrollable ResultSet, but this ResultSet is FORWARD_ONLY");
0624:
0625:                fetchDirection = direction;
0626:            }
0627:
0628:            /**
0629:             * JDBC 2.0 Return the fetch direction for this result set.
0630:             * 
0631:             * @return the fetch direction
0632:             * @exception SQLException if a database-access error occurs
0633:             */
0634:            public int getFetchDirection() throws SQLException {
0635:                return fetchDirection;
0636:            }
0637:
0638:            /**
0639:             * See performance issue explained in
0640:             * {@link org.continuent.sequoia.controller.virtualdatabase.VirtualDatabaseWorkerThread#fetchNextResultSetRows()}
0641:             * 
0642:             * @param rows the number of rows to fetch
0643:             * @exception SQLException if a database-access error occurs, or the condition
0644:             *              0 <= rows <= statement.getMaxRows() is not satisfied.
0645:             *              Currently ignored by this driver.
0646:             * @see ResultSet#setFetchSize(int)
0647:             */
0648:            public void setFetchSize(int rows) throws SQLException {
0649:                // This is just a hint afterall, let's not try to throw exceptions for
0650:                // nothing
0651:                if (rows < 0)
0652:                    throw new SQLException(
0653:                            "Value must be between 0 and getMaxRows()");
0654:
0655:                fetchSize = rows;
0656:            }
0657:
0658:            /**
0659:             * JDBC 2.0 Return the fetch size for this result set.
0660:             * 
0661:             * @return the fetch size
0662:             * @exception SQLException if a database-access error occurs
0663:             */
0664:            public int getFetchSize() throws SQLException {
0665:                return fetchSize;
0666:            }
0667:
0668:            //
0669:            // ---------------------------------------------------------------------
0670:            // Getter's and Setter's
0671:            // ---------------------------------------------------------------------
0672:            //
0673:
0674:            /**
0675:             * Get the value of a column in the current row as a Java String
0676:             * 
0677:             * @param columnIndex the first column is 1, the second is 2...
0678:             * @return the column value, null for SQL NULL
0679:             * @exception SQLException if a database access error occurs
0680:             */
0681:            public String getString(int columnIndex) throws SQLException {
0682:                checkRowAndColPosAndSetNullFlag(columnIndex);
0683:
0684:                if (wasNullFlag)
0685:                    return null;
0686:
0687:                if (inserting || updating)
0688:                    return tempRow[columnIndex - 1].toString();
0689:                else {
0690:                    Object tmpData = (((Object[]) data.get(currentRow))[columnIndex - 1]);
0691:                    if (tmpData instanceof  byte[]) {
0692:                        String encoding = this .fields[columnIndex - 1]
0693:                                .getEncoding();
0694:                        if (encoding != null)
0695:                            try {
0696:                                return new String((byte[]) tmpData, encoding);
0697:                            } catch (UnsupportedEncodingException e) {
0698:                                throw (SQLException) new SQLException(
0699:                                        "UnsupportedEncodingException (to "
0700:                                                + encoding + ") : "
0701:                                                + e.getMessage()).initCause(e);
0702:                            }
0703:                        else
0704:                            return new String((byte[]) tmpData);
0705:                    }
0706:                    return tmpData.toString();
0707:                }
0708:            }
0709:
0710:            /**
0711:             * Get the value of a column in the current row as a Java boolean
0712:             * 
0713:             * @param columnIndex the first column is 1, the second is 2...
0714:             * @return the column value, false for SQL NULL
0715:             * @exception SQLException if a database access error occurs
0716:             */
0717:            public boolean getBoolean(int columnIndex) throws SQLException {
0718:                checkRowAndColPosAndSetNullFlag(columnIndex);
0719:
0720:                if (wasNullFlag)
0721:                    return false;
0722:
0723:                Object object;
0724:                if (inserting || updating)
0725:                    object = tempRow[columnIndex - 1];
0726:                else
0727:                    object = (((Object[]) data.get(currentRow))[columnIndex - 1]);
0728:
0729:                String stringVal = object.toString();
0730:                if ((stringVal != null) && (stringVal.length() > 0)) {
0731:                    stringVal = stringVal.toLowerCase();
0732:
0733:                    if ("t".equals(stringVal)) {
0734:                        return true;
0735:                    } else if ("f".equals(stringVal)) {
0736:                        return false;
0737:                    } else if ("true".equals(stringVal)) {
0738:                        return true;
0739:                    } else if ("false".equals(stringVal)) {
0740:                        return false;
0741:                    } else if ("1".equals(stringVal)) {
0742:                        return true;
0743:                    } else if ("0".equals(stringVal)) {
0744:                        return false;
0745:                    } else if ("y".equals(stringVal)) {
0746:                        return true;
0747:                    } else if ("n".equals(stringVal)) {
0748:                        return false;
0749:                    } else if ("yes".equals(stringVal)) {
0750:                        return true;
0751:                    } else if ("no".equals(stringVal)) {
0752:                        return false;
0753:                    } else if (object instanceof  Number) {
0754:                        int value = ((Number) object).intValue();
0755:                        if (value == 0)
0756:                            return false;
0757:                        else if (value == 1)
0758:                            return true;
0759:                        // else other value throw an exception
0760:                    }
0761:
0762:                    // we didn't find anything reasonable and throw an exception
0763:                    throw new SQLException("column value " + stringVal
0764:                            + " of type: " + object.getClass()
0765:                            + " could not be converted to boolean");
0766:                } else {
0767:                    return false;
0768:                }
0769:            }
0770:
0771:            /**
0772:             * Get the value of a column in the current row as a Java short.
0773:             * 
0774:             * @param columnIndex the first column is 1, the second is 2,...
0775:             * @return the column value; 0 if SQL NULL
0776:             * @exception SQLException if a database access error occurs
0777:             */
0778:            public short getShort(int columnIndex) throws SQLException {
0779:                checkRowAndColPosAndSetNullFlag(columnIndex);
0780:
0781:                if (wasNullFlag)
0782:                    return 0;
0783:
0784:                Object obj;
0785:                if (inserting || updating)
0786:                    obj = tempRow[columnIndex - 1];
0787:                else
0788:                    obj = ((Object[]) data.get(currentRow))[columnIndex - 1];
0789:
0790:                if (obj instanceof  Number) {
0791:                    return ((Number) obj).shortValue();
0792:                }
0793:
0794:                // the object is not of type number we parse the string representation
0795:                try {
0796:                    String string = obj.toString();
0797:                    string = string.trim();
0798:                    return Short.parseShort(string);
0799:                } catch (NumberFormatException e) {
0800:                    // Try to convert a boolean
0801:                    String string = obj.toString().toLowerCase().trim();
0802:                    if ("true".equals(string))
0803:                        return 1;
0804:                    else if ("false".equals(string))
0805:                        return 0;
0806:                    throw new SQLException("the value " + obj.toString()
0807:                            + " is not a valid short number");
0808:                }
0809:            }
0810:
0811:            /**
0812:             * Get the value of a column in the current row as a Java int.
0813:             * 
0814:             * @param columnIndex the first column is 1, the second is 2,...
0815:             * @return the column value; 0 if SQL NULL
0816:             * @exception SQLException if a database access error occurs
0817:             */
0818:            public int getInt(int columnIndex) throws SQLException {
0819:                checkRowAndColPosAndSetNullFlag(columnIndex);
0820:
0821:                if (wasNullFlag)
0822:                    return 0;
0823:
0824:                Object obj;
0825:                if (inserting || updating)
0826:                    obj = tempRow[columnIndex - 1];
0827:                else
0828:                    obj = ((Object[]) data.get(currentRow))[columnIndex - 1];
0829:
0830:                if (obj instanceof  Number) {
0831:                    return ((Number) obj).intValue();
0832:                }
0833:
0834:                // the object is not of type number we parse the string representation
0835:                try {
0836:                    String string = obj.toString();
0837:                    string = string.trim();
0838:                    return Integer.parseInt(string);
0839:                } catch (NumberFormatException e) {
0840:                    // Try to convert a boolean
0841:                    String string = obj.toString().toLowerCase().trim();
0842:                    if ("true".equals(string))
0843:                        return 1;
0844:                    else if ("false".equals(string))
0845:                        return 0;
0846:                    throw new SQLException("the value " + obj.toString()
0847:                            + " is not a valid int number");
0848:                }
0849:            }
0850:
0851:            /**
0852:             * Get the value of a column in the current row as a Java long.
0853:             * 
0854:             * @param columnIndex the first column is 1, the second is 2,...
0855:             * @return the column value; 0 if SQL NULL
0856:             * @exception SQLException if a database access error occurs
0857:             */
0858:            public long getLong(int columnIndex) throws SQLException {
0859:                checkRowAndColPosAndSetNullFlag(columnIndex);
0860:
0861:                if (wasNullFlag)
0862:                    return 0;
0863:
0864:                Object obj;
0865:                if (inserting || updating)
0866:                    obj = tempRow[columnIndex - 1];
0867:                else
0868:                    obj = ((Object[]) data.get(currentRow))[columnIndex - 1];
0869:
0870:                if (obj instanceof  Number) {
0871:                    return ((Number) obj).longValue();
0872:                }
0873:
0874:                // the object is not of type number we parse the string representation
0875:                try {
0876:                    String string = obj.toString();
0877:                    string = string.trim();
0878:                    return Long.parseLong(string);
0879:                } catch (NumberFormatException e) {
0880:                    // Try to convert a boolean
0881:                    String string = obj.toString().toLowerCase().trim();
0882:                    if ("true".equals(string))
0883:                        return 1;
0884:                    else if ("false".equals(string))
0885:                        return 0;
0886:                    throw new SQLException("the value " + obj.toString()
0887:                            + " is not a valid long number");
0888:                }
0889:            }
0890:
0891:            /**
0892:             * Get the value of a column in the current row as a Java float.
0893:             * 
0894:             * @param columnIndex the first column is 1, the second is 2,...
0895:             * @return the column value; 0 if SQL NULL
0896:             * @exception SQLException if a database access error occurs
0897:             */
0898:            public float getFloat(int columnIndex) throws SQLException {
0899:                checkRowAndColPosAndSetNullFlag(columnIndex);
0900:
0901:                if (wasNullFlag)
0902:                    return 0;
0903:
0904:                Object obj;
0905:                if (inserting || updating)
0906:                    obj = tempRow[columnIndex - 1];
0907:                else
0908:                    obj = ((Object[]) data.get(currentRow))[columnIndex - 1];
0909:
0910:                if (obj instanceof  Number) {
0911:                    return ((Number) obj).floatValue();
0912:                }
0913:
0914:                // the object is not of type number we parse the string representation
0915:                try {
0916:                    String string = obj.toString();
0917:                    string = string.trim();
0918:                    return Float.parseFloat(string);
0919:                } catch (NumberFormatException e) {
0920:                    // Try to convert a boolean
0921:                    String string = obj.toString().toLowerCase().trim();
0922:                    if ("true".equals(string))
0923:                        return 1;
0924:                    else if ("false".equals(string))
0925:                        return 0;
0926:                    throw new SQLException("the value " + obj.toString()
0927:                            + " is not a valid float number");
0928:                }
0929:            }
0930:
0931:            /**
0932:             * Get the value of a column in the current row as a Java double.
0933:             * 
0934:             * @param columnIndex the first column is 1, the second is 2,...
0935:             * @return the column value; 0 if SQL NULL
0936:             * @exception SQLException if a database access error occurs
0937:             */
0938:            public double getDouble(int columnIndex) throws SQLException {
0939:                checkRowAndColPosAndSetNullFlag(columnIndex);
0940:
0941:                if (wasNullFlag)
0942:                    return 0;
0943:
0944:                Object obj;
0945:                if (inserting || updating)
0946:                    obj = tempRow[columnIndex - 1];
0947:                else
0948:                    obj = ((Object[]) data.get(currentRow))[columnIndex - 1];
0949:
0950:                if (obj instanceof  Number) {
0951:                    return ((Number) obj).doubleValue();
0952:                }
0953:
0954:                // the object is not of type number we parse the string representation
0955:                try {
0956:                    String string = obj.toString();
0957:                    string = string.trim();
0958:                    return Double.parseDouble(string);
0959:                } catch (NumberFormatException e) {
0960:                    // Try to convert a boolean
0961:                    String string = obj.toString().toLowerCase().trim();
0962:                    if ("true".equals(string))
0963:                        return 1;
0964:                    else if ("false".equals(string))
0965:                        return 0;
0966:                    throw new SQLException("the value " + obj.toString()
0967:                            + " is not a valid double number");
0968:                }
0969:            }
0970:
0971:            /**
0972:             * Get the value of a column in the current row as a java.lang.BigDecimal
0973:             * object
0974:             * 
0975:             * @param columnIndex the first column is 1, the second is 2...
0976:             * @param scale the number of digits to the right of the decimal
0977:             * @return the column value; if the value is SQL NULL, null
0978:             * @exception SQLException if a database access error occurs
0979:             * @deprecated
0980:             */
0981:            public BigDecimal getBigDecimal(int columnIndex, int scale)
0982:                    throws SQLException {
0983:                BigDecimal bigDecimal = getBigDecimal(columnIndex);
0984:                if (bigDecimal == null)
0985:                    return null;
0986:                else
0987:                    return bigDecimal.setScale(scale);
0988:            }
0989:
0990:            /**
0991:             * Get the value of a column in the current row as a Java byte array.
0992:             * <p>
0993:             * <b>Be warned </b> If the blob is huge, then you may run out of memory.
0994:             * 
0995:             * @param columnIndex the first column is 1, the second is 2, ...
0996:             * @return the column value; if the value is SQL NULL, the result is null
0997:             * @exception SQLException if a database access error occurs
0998:             */
0999:            public byte[] getBytes(int columnIndex) throws SQLException {
1000:                checkRowAndColPosAndSetNullFlag(columnIndex);
1001:
1002:                if (wasNullFlag)
1003:                    return null;
1004:
1005:                Object o;
1006:                if (inserting || updating)
1007:                    o = tempRow[columnIndex - 1];
1008:                else
1009:                    o = ((Object[]) data.get(currentRow))[columnIndex - 1];
1010:
1011:                byte[] maybeEncodedBytes;
1012:                if (o instanceof  byte[]) {
1013:                    maybeEncodedBytes = (byte[]) o;
1014:                } else if (o instanceof  ByteArrayBlob) {
1015:                    ByteArrayBlob b = (ByteArrayBlob) o;
1016:                    // TODO: use getBinaryStream() to avoid the copy
1017:                    maybeEncodedBytes = b.getBytes(1, (int) b.length());
1018:                } else {
1019:                    throw new NotImplementedException("in getBytes("
1020:                            + columnIndex
1021:                            + "), don't know how to convert type "
1022:                            + o.getClass().getName() + " into a byte array ");
1023:                }
1024:
1025:                return maybeEncodedBytes; // maybe not!
1026:            }
1027:
1028:            /**
1029:             * Get the value of a column in the current row as a java.sql.Date object
1030:             * 
1031:             * @param columnIndex the first column is 1, the second is 2...
1032:             * @return the column value; null if SQL NULL
1033:             * @exception SQLException if a database access error occurs
1034:             */
1035:            public java.sql.Date getDate(int columnIndex) throws SQLException {
1036:                checkRowAndColPosAndSetNullFlag(columnIndex);
1037:
1038:                if (wasNullFlag)
1039:                    return null;
1040:
1041:                // we may be reading a timestamp column and have to convert it to date
1042:                // the client is asking for the date field only, we have to make sure
1043:                // hour,minutes,... are cleared
1044:                String dateString;
1045:                if (inserting || updating)
1046:                    dateString = tempRow[columnIndex - 1].toString();
1047:                else
1048:                    dateString = ((Object[]) data.get(currentRow))[columnIndex - 1]
1049:                            .toString();
1050:
1051:                if (dateString.length() == 10)
1052:                    return java.sql.Date.valueOf(dateString);
1053:                else
1054:                    return java.sql.Date.valueOf(dateString.substring(0, 10));
1055:            }
1056:
1057:            /**
1058:             * Get the value of a column in the current row as a java.sql.Time object
1059:             * 
1060:             * @param columnIndex the first column is 1, the second is 2...
1061:             * @return the column value; null if SQL NULL
1062:             * @exception SQLException if a database access error occurs
1063:             */
1064:            public Time getTime(int columnIndex) throws SQLException {
1065:                checkRowAndColPosAndSetNullFlag(columnIndex);
1066:
1067:                if (wasNullFlag)
1068:                    return null;
1069:
1070:                Object obj;
1071:                if (inserting || updating)
1072:                    obj = tempRow[columnIndex - 1];
1073:                else
1074:                    obj = ((Object[]) data.get(currentRow))[columnIndex - 1];
1075:
1076:                if (obj instanceof  java.util.Date) {
1077:                    java.util.Date time = (java.util.Date) obj;
1078:                    // the driver returns the format of the column, but we are asking for
1079:                    // the time values only.
1080:                    String timeString = time.toString();
1081:                    if (timeString.length() == 8) {
1082:                        // ok we have got a timefield of the format HH:mm:ss, exactly the way
1083:                        // we need it, no further processing is required
1084:                        return new Time(time.getTime());
1085:                    }
1086:
1087:                    // we have got the date fields too and have to clear the year, month and
1088:                    // date field
1089:                    Calendar cal = Calendar.getInstance();
1090:                    cal.setTime(time);
1091:                    cal.clear(Calendar.YEAR);
1092:                    cal.clear(Calendar.MONTH);
1093:                    cal.clear(Calendar.DATE);
1094:                    cal.clear(Calendar.MILLISECOND);
1095:                    return new Time(cal.getTimeInMillis());
1096:                }
1097:
1098:                // the object is not of type date we parse the string representation
1099:                try {
1100:                    String string = obj.toString();
1101:                    string = string.trim();
1102:                    return Time.valueOf(string);
1103:                } catch (IllegalArgumentException e) {
1104:                    throw new SQLException("the value " + obj.toString()
1105:                            + " is not a valid time");
1106:                }
1107:            }
1108:
1109:            /**
1110:             * Get the value of a column in the current row as a java.sql.Timestamp object
1111:             * 
1112:             * @param columnIndex the first column is 1, the second is 2...
1113:             * @return the column value; null if SQL NULL
1114:             * @exception SQLException if a database access error occurs
1115:             */
1116:            public Timestamp getTimestamp(int columnIndex) throws SQLException {
1117:                checkRowAndColPosAndSetNullFlag(columnIndex);
1118:
1119:                if (wasNullFlag)
1120:                    return null;
1121:
1122:                Object obj;
1123:                if (inserting || updating)
1124:                    obj = tempRow[columnIndex - 1];
1125:                else
1126:                    obj = ((Object[]) data.get(currentRow))[columnIndex - 1];
1127:
1128:                if (obj instanceof  java.util.Date) {
1129:                    return new Timestamp(((java.util.Date) obj).getTime());
1130:                }
1131:
1132:                // the object is not of type timestamp we parse the string representation
1133:                try {
1134:                    String string = obj.toString();
1135:                    string = string.trim();
1136:                    return Timestamp.valueOf(string);
1137:                } catch (IllegalArgumentException e) {
1138:                    throw new SQLException("the value " + obj.toString()
1139:                            + " is not a valid timestamp");
1140:                }
1141:            }
1142:
1143:            /**
1144:             * A column value can be retrieved as a stream of ASCII characters and then
1145:             * read in chunks from the stream. This method is particulary suitable for
1146:             * retrieving large LONGVARCHAR values. The JDBC driver will do any necessary
1147:             * conversion from the database format into ASCII.
1148:             * <p>
1149:             * <B>Note: </B> All the data in the returned stream must be read prior to
1150:             * getting the value of any other column. The next call to a get method
1151:             * implicitly closes the stream. Also, a stream may return 0 for available()
1152:             * whether there is data available or not.
1153:             * 
1154:             * @param columnIndex the first column is 1, the second is 2, ...
1155:             * @return a Java InputStream that delivers the database column value as a
1156:             *         stream of one byte ASCII characters. If the value is SQL NULL then
1157:             *         the result is null
1158:             * @exception SQLException if a database access error occurs
1159:             * @see #getBinaryStream(int)
1160:             */
1161:            public InputStream getAsciiStream(int columnIndex)
1162:                    throws SQLException {
1163:                checkRowAndColPosAndSetNullFlag(columnIndex);
1164:
1165:                try { // TODO: actually implement a "streaming" encoding instead of encoding
1166:                    // everything at once. See SEQUOIA-400
1167:                    currentStream = new ByteArrayInputStream(Charset.forName(
1168:                            "US-ASCII").newEncoder().encode(
1169:                            CharBuffer.wrap(getString(columnIndex))).array());
1170:                } catch (CharacterCodingException e) {
1171:                    throw (SQLException) new SQLException(
1172:                            "Caught CharacterCodingException (data is probably not ASCII): "
1173:                                    + e.getMessage()).initCause(e);
1174:                }
1175:                return currentStream;
1176:            }
1177:
1178:            /**
1179:             * A column value can also be retrieved as a stream of Unicode characters. We
1180:             * implement this as a binary stream.
1181:             * 
1182:             * @param columnIndex the first column is 1, the second is 2...
1183:             * @return a Java InputStream that delivers the database column value as a
1184:             *         stream of two byte Unicode characters. If the value is SQL NULL,
1185:             *         then the result is null
1186:             * @exception SQLException if a database access error occurs
1187:             * @deprecated
1188:             * @see #getAsciiStream
1189:             * @see #getBinaryStream(int)
1190:             */
1191:            public InputStream getUnicodeStream(int columnIndex)
1192:                    throws SQLException {
1193:                checkRowAndColPosAndSetNullFlag(columnIndex);
1194:
1195:                currentStream = new ByteArrayInputStream(getString(columnIndex)
1196:                        .getBytes());
1197:                return currentStream;
1198:            }
1199:
1200:            /**
1201:             * A column value can also be retrieved as a binary strea. This method is
1202:             * suitable for retrieving LONGVARBINARY values.
1203:             * 
1204:             * @param columnIndex the first column is 1, the second is 2...
1205:             * @return a Java InputStream that delivers the database column value as a
1206:             *         stream of bytes. If the value is SQL NULL, then the result is null
1207:             * @exception SQLException if a database access error occurs
1208:             * @see #getAsciiStream(int)
1209:             * @see #getUnicodeStream(int)
1210:             */
1211:
1212:            public InputStream getBinaryStream(int columnIndex)
1213:                    throws SQLException {
1214:                checkRowAndColPosAndSetNullFlag(columnIndex);
1215:
1216:                byte[] b = getBytes(columnIndex);
1217:                if (b != null) {
1218:                    currentStream = new ByteArrayInputStream(b);
1219:                    return currentStream;
1220:                } else
1221:                    return null; // SQL NULL
1222:            }
1223:
1224:            /**
1225:             * The following routines simply convert the columnName into a columnIndex and
1226:             * then call the appropriate routine above.
1227:             * 
1228:             * @param columnName is the SQL name of the column
1229:             * @return the column value
1230:             * @exception SQLException if a database access error occurs
1231:             */
1232:            public String getString(String columnName) throws SQLException {
1233:                return this .getString(findColumn(columnName));
1234:            }
1235:
1236:            /**
1237:             * @see java.sql.ResultSet#getBoolean(java.lang.String)
1238:             */
1239:            public boolean getBoolean(String columnName) throws SQLException {
1240:                return getBoolean(findColumn(columnName));
1241:            }
1242:
1243:            /**
1244:             * @see java.sql.ResultSet#getByte(java.lang.String)
1245:             */
1246:            public byte getByte(String columnName) throws SQLException {
1247:                return getByte(findColumn(columnName));
1248:            }
1249:
1250:            /**
1251:             * @see java.sql.ResultSet#getShort(java.lang.String)
1252:             */
1253:            public short getShort(String columnName) throws SQLException {
1254:                return getShort(findColumn(columnName));
1255:            }
1256:
1257:            /**
1258:             * @see java.sql.ResultSet#getInt(java.lang.String)
1259:             */
1260:            public int getInt(String columnName) throws SQLException {
1261:                return getInt(findColumn(columnName));
1262:            }
1263:
1264:            /**
1265:             * @see java.sql.ResultSet#getLong(java.lang.String)
1266:             */
1267:            public long getLong(String columnName) throws SQLException {
1268:                return getLong(findColumn(columnName));
1269:            }
1270:
1271:            /**
1272:             * @see java.sql.ResultSet#getFloat(java.lang.String)
1273:             */
1274:            public float getFloat(String columnName) throws SQLException {
1275:                return getFloat(findColumn(columnName));
1276:            }
1277:
1278:            /**
1279:             * @see java.sql.ResultSet#getDouble(java.lang.String)
1280:             */
1281:            public double getDouble(String columnName) throws SQLException {
1282:                return getDouble(findColumn(columnName));
1283:            }
1284:
1285:            /**
1286:             * @see java.sql.ResultSet#getBigDecimal(String, int)
1287:             * @deprecated
1288:             */
1289:            public BigDecimal getBigDecimal(String columnName, int scale)
1290:                    throws SQLException {
1291:                return getBigDecimal(findColumn(columnName), scale);
1292:            }
1293:
1294:            /**
1295:             * @see java.sql.ResultSet#getBytes(java.lang.String)
1296:             */
1297:            public byte[] getBytes(String columnName) throws SQLException {
1298:                return getBytes(findColumn(columnName));
1299:            }
1300:
1301:            /**
1302:             * @see java.sql.ResultSet#getDate(java.lang.String)
1303:             */
1304:            public java.sql.Date getDate(String columnName) throws SQLException {
1305:                return getDate(findColumn(columnName));
1306:            }
1307:
1308:            /**
1309:             * @see java.sql.ResultSet#getTime(java.lang.String)
1310:             */
1311:            public Time getTime(String columnName) throws SQLException {
1312:                return getTime(findColumn(columnName));
1313:            }
1314:
1315:            /**
1316:             * @see java.sql.ResultSet#getTimestamp(java.lang.String)
1317:             */
1318:            public Timestamp getTimestamp(String columnName)
1319:                    throws SQLException {
1320:                return getTimestamp(findColumn(columnName));
1321:            }
1322:
1323:            /**
1324:             * @see java.sql.ResultSet#getAsciiStream(java.lang.String)
1325:             */
1326:            public InputStream getAsciiStream(String columnName)
1327:                    throws SQLException {
1328:                return getAsciiStream(findColumn(columnName));
1329:            }
1330:
1331:            /**
1332:             * @see java.sql.ResultSet#getUnicodeStream(String)
1333:             * @deprecated
1334:             */
1335:            public InputStream getUnicodeStream(String columnName)
1336:                    throws SQLException {
1337:                return getUnicodeStream(findColumn(columnName));
1338:            }
1339:
1340:            /**
1341:             * @see java.sql.ResultSet#getBinaryStream(java.lang.String)
1342:             */
1343:            public InputStream getBinaryStream(String columnName)
1344:                    throws SQLException {
1345:                return getBinaryStream(findColumn(columnName));
1346:            }
1347:
1348:            /**
1349:             * The first warning reported by calls on this ResultSet is returned.
1350:             * Subsequent ResultSet warnings will be chained to this java.sql.SQLWarning.
1351:             * <p>
1352:             * The warning chain is automatically cleared each time a new row is read.
1353:             * <p>
1354:             * <B>Note: </B> This warning chain only covers warnings caused by ResultSet
1355:             * methods. Any warnings caused by statement methods (such as reading OUT
1356:             * parameters) will be chained on the Statement object.
1357:             * 
1358:             * @return the first java.sql.SQLWarning or null;
1359:             * @exception SQLException if a database access error occurs or this method is
1360:             *              called on a closed result set
1361:             */
1362:            public java.sql.SQLWarning getWarnings() throws SQLException {
1363:                checkIfClosed();
1364:                return connection.convertToSQLWarnings(warnings);
1365:            }
1366:
1367:            /**
1368:             * After this call, getWarnings returns null until a new warning is reported
1369:             * for this ResultSet
1370:             * 
1371:             * @exception SQLException if a database access error occurs
1372:             */
1373:
1374:            public void clearWarnings() throws SQLException {
1375:                warnings = null;
1376:            }
1377:
1378:            SQLWarning getStatementWarnings() {
1379:                return statementWarnings;
1380:            }
1381:
1382:            void setStatementWarnings(SQLWarning sqlw) {
1383:                statementWarnings = sqlw;
1384:            }
1385:
1386:            /**
1387:             * @see java.sql.ResultSet#getCursorName()
1388:             */
1389:            public String getCursorName() throws SQLException {
1390:                return cursorName;
1391:            }
1392:
1393:            /**
1394:             * Get the value of a column in the current row as a Java object
1395:             * <p>
1396:             * This method will return the value of the given column as a Java object. The
1397:             * type of the Java object will be the default Java Object type corresponding
1398:             * to the column's SQL type, following the mapping specified in the JDBC
1399:             * specification.
1400:             * <p>
1401:             * This method may also be used to read database specific abstract data types.
1402:             * 
1403:             * @param columnIndex the first column is 1, the second is 2...
1404:             * @return a Object holding the column value
1405:             * @exception SQLException if a database access error occurs
1406:             */
1407:            public Object getObject(int columnIndex) throws SQLException {
1408:                checkRowAndColPosAndSetNullFlag(columnIndex);
1409:
1410:                if (wasNullFlag)
1411:                    return null;
1412:
1413:                Object o;
1414:                if (inserting || updating)
1415:                    o = tempRow[columnIndex];
1416:                else
1417:                    o = ((Object[]) data.get(currentRow))[columnIndex - 1];
1418:                return o;
1419:            }
1420:
1421:            /**
1422:             * Get the value of a column in the current row as a Java object
1423:             * <p>
1424:             * This method will return the value of the given column as a Java object. The
1425:             * type of the Java object will be the default Java Object type corresponding
1426:             * to the column's SQL type, following the mapping specified in the JDBC
1427:             * specification.
1428:             * <p>
1429:             * This method may also be used to read database specific abstract data types.
1430:             * 
1431:             * @param columnName is the SQL name of the column
1432:             * @return a Object holding the column value
1433:             * @exception SQLException if a database access error occurs
1434:             */
1435:            public Object getObject(String columnName) throws SQLException {
1436:                return getObject(findColumn(columnName));
1437:            }
1438:
1439:            // --------------------------JDBC 2.0-----------------------------------
1440:
1441:            /**
1442:             * @see java.sql.ResultSet#getCharacterStream(int)
1443:             */
1444:            public java.io.Reader getCharacterStream(int columnIndex)
1445:                    throws SQLException {
1446:                String s = getString(columnIndex);
1447:                if (s == null)
1448:                    return null;
1449:                char[] content = s.toCharArray();
1450:                return new java.io.CharArrayReader(content);
1451:            }
1452:
1453:            /**
1454:             * @see java.sql.ResultSet#getCharacterStream(java.lang.String)
1455:             */
1456:            public java.io.Reader getCharacterStream(String columnName)
1457:                    throws SQLException {
1458:                return getCharacterStream(findColumn(columnName));
1459:            }
1460:
1461:            /**
1462:             * JDBC 2.0 Get the value of a column in the current row as a
1463:             * java.math.BigDecimal object.
1464:             * 
1465:             * @param columnIndex the first column is 1, the second is 2, ...
1466:             * @return the column value (full precision); if the value is SQL NULL, the
1467:             *         result is null
1468:             * @exception SQLException if a database-access error occurs.
1469:             */
1470:            public BigDecimal getBigDecimal(int columnIndex)
1471:                    throws SQLException {
1472:                checkRowAndColPosAndSetNullFlag(columnIndex);
1473:
1474:                if (wasNullFlag)
1475:                    return null;
1476:
1477:                Object obj;
1478:                if (inserting || updating)
1479:                    obj = tempRow[columnIndex - 1];
1480:                else
1481:                    obj = ((Object[]) data.get(currentRow))[columnIndex - 1];
1482:
1483:                if (obj instanceof  BigDecimal)
1484:                    return (BigDecimal) obj;
1485:                else if (obj instanceof  Long) {
1486:                    return new BigDecimal(((Long) obj).longValue());
1487:                } else if (obj instanceof  BigInteger) {
1488:                    return new BigDecimal(((BigInteger) obj));
1489:                } else if (obj instanceof  Short) {
1490:                    return new BigDecimal(((Short) obj).shortValue());
1491:                } else if (obj instanceof  Integer) {
1492:                    return new BigDecimal(((Integer) obj).intValue());
1493:                } else if (obj instanceof  String) {
1494:                    return new BigDecimal((String) obj);
1495:                } else if (obj instanceof  Number) {
1496:                    // float and double have to be converted via string
1497:                    // othwerwise we produce errors
1498:                    // javadoc for BigDecimal :
1499:                    // Note: the results of this constructor can be somewhat unpredictable.
1500:                    // One might assume that new BigDecimal(.1) is exactly equal to .1, but
1501:                    // it is actually equal to
1502:                    // .1000000000000000055511151231257827021181583404541015625. This is so
1503:                    // because .1 cannot be represented exactly as a double (or, for that
1504:                    // matter, as a binary fraction of any finite length). Thus, the long
1505:                    // value that is being passed in to the constructor is not exactly equal
1506:                    // to .1, appearances nonwithstanding.
1507:
1508:                    // The (String) constructor, on the other hand, is perfectly
1509:                    // predictable: new BigDecimal(".1") is exactly equal to .1, as one
1510:                    // would expect. Therefore, it is generally recommended that the
1511:                    // (String) constructor be used in preference to this one.
1512:                    return new BigDecimal(obj.toString());
1513:                } else if (obj instanceof  Boolean) {
1514:                    // Try to convert a boolean
1515:                    String string = obj.toString().toLowerCase().trim();
1516:                    if ("true".equals(string))
1517:                        return new BigDecimal(1);
1518:                    else if ("false".equals(string))
1519:                        return new BigDecimal(0);
1520:                    throw new SQLException("Type " + obj.getClass().getName()
1521:                            + " is not compatible with BigDecimal");
1522:
1523:                } else {
1524:                    throw new SQLException("Type " + obj.getClass().getName()
1525:                            + " is not compatible with BigDecimal");
1526:                }
1527:            }
1528:
1529:            /**
1530:             * @see java.sql.ResultSet#getBigDecimal(java.lang.String)
1531:             */
1532:            public BigDecimal getBigDecimal(String columnName)
1533:                    throws SQLException {
1534:                return getBigDecimal(findColumn(columnName));
1535:            }
1536:
1537:            /**
1538:             * JDBC 2.0 Returns the value of column as a Java object. Use the map to
1539:             * determine the class from which to construct data of SQL structured and
1540:             * distinct types.
1541:             * 
1542:             * @param i the first column is 1, the second is 2, ...
1543:             * @param map the mapping from SQL type names to Java classes
1544:             * @return an object representing the SQL value
1545:             * @exception SQLException if a database-access error occurs.
1546:             */
1547:            public Object getObject(int i, java.util.Map map)
1548:                    throws SQLException {
1549:                throw new NotImplementedException(
1550:                        "getObject(int, java.util.Map)");
1551:            }
1552:
1553:            /**
1554:             * JDBC 2.0 Get a REF(&lt;structured-type&gt;) column.
1555:             * 
1556:             * @param i the first column is 1, the second is 2, ...
1557:             * @return an object representing data of an SQL REF type
1558:             * @exception SQLException if a database-access error occurs.
1559:             */
1560:            public java.sql.Ref getRef(int i) throws SQLException {
1561:                checkRowAndColPosAndSetNullFlag(i);
1562:
1563:                if (wasNullFlag)
1564:                    return null;
1565:
1566:                if (inserting || updating)
1567:                    return (Ref) tempRow[i - 1];
1568:                else
1569:                    return (Ref) (((Object[]) data.get(currentRow))[i - 1]);
1570:            }
1571:
1572:            /**
1573:             * JDBC 2.0 Gets a BLOB column.
1574:             * 
1575:             * @param columnIndex the first column is 1, the second is 2, ...
1576:             * @return an object representing a BLOB
1577:             * @exception SQLException if a database-access error occurs.
1578:             */
1579:            public java.sql.Blob getBlob(int columnIndex) throws SQLException {
1580:                checkRowAndColPosAndSetNullFlag(columnIndex);
1581:
1582:                if (wasNullFlag)
1583:                    return null;
1584:
1585:                Object o;
1586:                if (inserting || updating)
1587:                    o = tempRow[columnIndex - 1];
1588:                else
1589:                    o = (((Object[]) data.get(currentRow))[columnIndex - 1]);
1590:
1591:                // getBytes() does decode
1592:                if (o instanceof  ByteArrayBlob || o instanceof  byte[])
1593:                    return new ByteArrayBlob(getBytes(columnIndex));
1594:                else
1595:                    throw new NotImplementedException("in getBlob("
1596:                            + columnIndex
1597:                            + "), don't know how to convert type "
1598:                            + o.getClass().getName() + " into a Blob");
1599:            }
1600:
1601:            /**
1602:             * JDBC 2.0 Gets a CLOB column.
1603:             * 
1604:             * @param columnIndex the first column is 1, the second is 2, ...
1605:             * @return an object representing a CLOB
1606:             * @exception SQLException if a database-access error occurs.
1607:             */
1608:            public java.sql.Clob getClob(int columnIndex) throws SQLException {
1609:                checkRowAndColPosAndSetNullFlag(columnIndex);
1610:
1611:                if (wasNullFlag)
1612:                    return null;
1613:
1614:                Object o;
1615:                if (inserting || updating)
1616:                    o = tempRow[columnIndex - 1];
1617:                else
1618:                    o = (((Object[]) data.get(currentRow))[columnIndex - 1]);
1619:
1620:                // Test if the type of the Clob is indeed a Clob or just a String
1621:                // throw new SQLException("Class:"+o.getClass());
1622:                if (o instanceof  String)
1623:                    return new StringClob((String) o);
1624:                else if (o instanceof  Clob)
1625:                    return (java.sql.Clob) o;
1626:                else
1627:                    // FIXME: Huh? What it is the purpose of this?
1628:                    return new StringClob(new String(o.toString()));
1629:            }
1630:
1631:            /**
1632:             * JDBC 2.0 Gets an array column.
1633:             * 
1634:             * @param columnIndex the first column is 1, the second is 2, ...
1635:             * @return an object representing an SQL array
1636:             * @exception SQLException if a database-access error occurs.
1637:             */
1638:            public java.sql.Array getArray(int columnIndex) throws SQLException {
1639:                checkRowAndColPosAndSetNullFlag(columnIndex);
1640:
1641:                if (wasNullFlag)
1642:                    return null;
1643:
1644:                if (inserting || updating)
1645:                    return (java.sql.Array) tempRow[columnIndex - 1];
1646:                else
1647:                    return (java.sql.Array) (((Object[]) data.get(currentRow))[columnIndex - 1]);
1648:            }
1649:
1650:            /**
1651:             * JDBC 2.0 Returns the value of column as a Java object. Use the map to
1652:             * determine the class from which to construct data of SQL structured and
1653:             * distinct types.
1654:             * 
1655:             * @param colName the column name
1656:             * @param map the mapping from SQL type names to Java classes
1657:             * @return an object representing the SQL value
1658:             * @exception SQLException if a database-access error occurs.
1659:             */
1660:            public Object getObject(String colName, java.util.Map map)
1661:                    throws SQLException {
1662:                return getObject(findColumn(colName), map);
1663:            }
1664:
1665:            /**
1666:             * JDBC 2.0 Get a REF(&lt;structured-type&gt;) column.
1667:             * 
1668:             * @param colName the column name
1669:             * @return an object representing data of an SQL REF type
1670:             * @exception SQLException if a database-access error occurs.
1671:             */
1672:            public java.sql.Ref getRef(String colName) throws SQLException {
1673:                return getRef(findColumn(colName));
1674:            }
1675:
1676:            /**
1677:             * JDBC 2.0 Get a BLOB column.
1678:             * 
1679:             * @param colName the column name
1680:             * @return an object representing a BLOB
1681:             * @exception SQLException if a database-access error occurs.
1682:             */
1683:            public java.sql.Blob getBlob(String colName) throws SQLException {
1684:                return getBlob(findColumn(colName));
1685:            }
1686:
1687:            /**
1688:             * JDBC 2.0 Get a CLOB column.
1689:             * 
1690:             * @param colName the column name
1691:             * @return an object representing a CLOB
1692:             * @exception SQLException if a database-access error occurs.
1693:             */
1694:            public java.sql.Clob getClob(String colName) throws SQLException {
1695:                return getClob(findColumn(colName));
1696:            }
1697:
1698:            /**
1699:             * JDBC 2.0 Get an array column.
1700:             * 
1701:             * @param colName the column name
1702:             * @return an object representing an SQL array
1703:             * @exception SQLException if a database-access error occurs.
1704:             */
1705:            public java.sql.Array getArray(String colName) throws SQLException {
1706:                return getArray(findColumn(colName));
1707:            }
1708:
1709:            /**
1710:             * JDBC 2.0 Get the value of a column in the current row as a java.sql.Date
1711:             * object. Use the calendar to construct an appropriate millisecond value for
1712:             * the Date, if the underlying database doesn't store timezone information.
1713:             * 
1714:             * @param columnIndex the first column is 1, the second is 2, ...
1715:             * @param cal the calendar to use in constructing the date (ignored)
1716:             * @return the column value; if the value is SQL NULL, the result is null
1717:             * @exception SQLException if a database-access error occurs.
1718:             */
1719:            public java.sql.Date getDate(int columnIndex, Calendar cal)
1720:                    throws SQLException {
1721:                return getDate(columnIndex);
1722:            }
1723:
1724:            /**
1725:             * Get the value of a column in the current row as a java.sql.Date object. Use
1726:             * the calendar to construct an appropriate millisecond value for the Date, if
1727:             * the underlying database doesn't store timezone information.
1728:             * 
1729:             * @param columnName is the SQL name of the column
1730:             * @param cal the calendar to use in constructing the date
1731:             * @return the column value; if the value is SQL NULL, the result is null
1732:             * @exception SQLException if a database-access error occurs.
1733:             */
1734:            public java.sql.Date getDate(String columnName, Calendar cal)
1735:                    throws SQLException {
1736:                return getDate(findColumn(columnName), cal);
1737:            }
1738:
1739:            /**
1740:             * Get the value of a column in the current row as a java.sql.Time object. Use
1741:             * the calendar to construct an appropriate millisecond value for the Time, if
1742:             * the underlying database doesn't store timezone information.
1743:             * 
1744:             * @param columnIndex the first column is 1, the second is 2, ...
1745:             * @param cal the calendar to use in constructing the time
1746:             * @return the column value; if the value is SQL NULL, the result is null
1747:             * @exception SQLException if a database-access error occurs.
1748:             */
1749:            public java.sql.Time getTime(int columnIndex, Calendar cal)
1750:                    throws SQLException {
1751:                return getTime(columnIndex);
1752:            }
1753:
1754:            /**
1755:             * Get the value of a column in the current row as a java.sql.Time object. Use
1756:             * the calendar to construct an appropriate millisecond value for the Time, if
1757:             * the underlying database doesn't store timezone information.
1758:             * 
1759:             * @param columnName is the SQL name of the column
1760:             * @param cal the calendar to use in constructing the time
1761:             * @return the column value; if the value is SQL NULL, the result is null
1762:             * @exception SQLException if a database-access error occurs.
1763:             */
1764:            public java.sql.Time getTime(String columnName, Calendar cal)
1765:                    throws SQLException {
1766:                return getTime(findColumn(columnName), cal);
1767:            }
1768:
1769:            /**
1770:             * Get the value of a column in the current row as a java.sql.Timestamp
1771:             * object. Use the calendar to construct an appropriate millisecond value for
1772:             * the Timestamp, if the underlying database doesn't store timezone
1773:             * information.
1774:             * 
1775:             * @param columnIndex the first column is 1, the second is 2, ...
1776:             * @param cal the calendar to use in constructing the timestamp (ignored)
1777:             * @return the column value; if the value is SQL NULL, the result is null
1778:             * @exception SQLException if a database-access error occurs.
1779:             */
1780:            public java.sql.Timestamp getTimestamp(int columnIndex, Calendar cal)
1781:                    throws SQLException {
1782:                return getTimestamp(columnIndex);
1783:            }
1784:
1785:            /**
1786:             * Get the value of a column in the current row as a java.sql.Timestamp
1787:             * object. Use the calendar to construct an appropriate millisecond value for
1788:             * the Timestamp, if the underlying database doesn't store timezone
1789:             * information.
1790:             * 
1791:             * @param columnName is the SQL name of the column
1792:             * @param cal the calendar to use in constructing the timestamp
1793:             * @return the column value; if the value is SQL NULL, the result is null
1794:             * @exception SQLException if a database-access error occurs.
1795:             */
1796:            public java.sql.Timestamp getTimestamp(String columnName,
1797:                    Calendar cal) throws SQLException {
1798:                return getTimestamp(findColumn(columnName), cal);
1799:            }
1800:
1801:            // ---------------------------------------------------------------------
1802:            // Updates
1803:            // ---------------------------------------------------------------------
1804:
1805:            /**
1806:             * JDBC 2.0 Determine if the current row has been updated. The value returned
1807:             * depends on whether or not the result set can detect updates.
1808:             * 
1809:             * @return <code>true</code> if the row has been visibly updated by the
1810:             *         owner or another, and updates are detected
1811:             * @exception SQLException if a database-access error occurs
1812:             * @see DatabaseMetaData#updatesAreDetected
1813:             */
1814:            public boolean rowUpdated() throws SQLException {
1815:                throw new NotImplementedException("rowUpdated");
1816:            }
1817:
1818:            /**
1819:             * JDBC 2.0 Determine if the current row has been inserted. The value returned
1820:             * depends on whether or not the result set can detect visible inserts.
1821:             * 
1822:             * @return <code>true</code> if inserted and inserts are detected
1823:             * @exception SQLException if a database-access error occurs
1824:             * @see DatabaseMetaData#insertsAreDetected
1825:             */
1826:            public boolean rowInserted() throws SQLException {
1827:                throw new NotImplementedException("rowInserted");
1828:            }
1829:
1830:            /**
1831:             * JDBC 2.0 Determine if this row has been deleted. A deleted row may leave a
1832:             * visible "hole" in a result set. This method can be used to detect holes in
1833:             * a result set. The value returned depends on whether or not the result set
1834:             * can detect deletions.
1835:             * 
1836:             * @return <code>true</code> if deleted and deletes are detected
1837:             * @exception SQLException if a database-access error occurs
1838:             * @see DatabaseMetaData#deletesAreDetected
1839:             */
1840:            public boolean rowDeleted() throws SQLException {
1841:                throw new NotImplementedException("rowDeleted");
1842:            }
1843:
1844:            /**
1845:             * JDBC 2.0 Give a nullable column a null value. The updateXXX() methods are
1846:             * used to update column values in the current row, or the insert row. The
1847:             * updateXXX() methods do not update the underlying database, instead the
1848:             * updateRow() or insertRow() methods are called to update the database.
1849:             * 
1850:             * @param columnIndex the first column is 1, the second is 2, ...
1851:             * @exception SQLException if a database-access error occurs
1852:             */
1853:            public void updateNull(int columnIndex) throws SQLException {
1854:                checkIfClosed();
1855:
1856:                if (inserting)
1857:                    insertStatement.setNull(columnIndex,
1858:                            fields[columnIndex - 1].getSqlType());
1859:                else {
1860:                    checkUpdateFlagAndPrepareUpdateIfNeeded();
1861:                    updateStatement.setNull(columnIndex,
1862:                            fields[columnIndex - 1].getSqlType());
1863:                }
1864:
1865:                tempRow[columnIndex - 1] = null;
1866:            }
1867:
1868:            /**
1869:             * JDBC 2.0 Update a column with a boolean value. The updateXXX() methods are
1870:             * used to update column values in the current row, or the insert row. The
1871:             * updateXXX() methods do not update the underlying database, instead the
1872:             * updateRow() or insertRow() methods are called to update the database.
1873:             * 
1874:             * @param columnIndex the first column is 1, the second is 2, ...
1875:             * @param x the new column value
1876:             * @exception SQLException if a database-access error occurs
1877:             */
1878:
1879:            public void updateBoolean(int columnIndex, boolean x)
1880:                    throws SQLException {
1881:                checkIfClosed();
1882:
1883:                if (inserting)
1884:                    insertStatement.setBoolean(columnIndex, x);
1885:                else {
1886:                    checkUpdateFlagAndPrepareUpdateIfNeeded();
1887:                    updateStatement.setBoolean(columnIndex, x);
1888:                }
1889:
1890:                tempRow[columnIndex - 1] = Boolean.valueOf(x);
1891:            }
1892:
1893:            /**
1894:             * JDBC 2.0 Update a column with a byte value. The updateXXX() methods are
1895:             * used to update column values in the current row, or the insert row. The
1896:             * updateXXX() methods do not update the underlying database, instead the
1897:             * updateRow() or insertRow() methods are called to update the database.
1898:             * 
1899:             * @param columnIndex the first column is 1, the second is 2, ...
1900:             * @param x the new column value
1901:             * @exception SQLException if a database-access error occurs
1902:             */
1903:            public void updateByte(int columnIndex, byte x) throws SQLException {
1904:                checkIfClosed();
1905:
1906:                if (inserting)
1907:                    insertStatement.setByte(columnIndex, x);
1908:                else {
1909:                    checkUpdateFlagAndPrepareUpdateIfNeeded();
1910:                    updateStatement.setByte(columnIndex, x);
1911:                }
1912:
1913:                tempRow[columnIndex - 1] = new Byte(x);
1914:            }
1915:
1916:            /**
1917:             * JDBC 2.0 Update a column with a short value. The updateXXX() methods are
1918:             * used to update column values in the current row, or the insert row. The
1919:             * updateXXX() methods do not update the underlying database, instead the
1920:             * updateRow() or insertRow() methods are called to update the database.
1921:             * 
1922:             * @param columnIndex the first column is 1, the second is 2, ...
1923:             * @param x the new column value
1924:             * @exception SQLException if a database-access error occurs
1925:             */
1926:            public void updateShort(int columnIndex, short x)
1927:                    throws SQLException {
1928:                checkIfClosed();
1929:
1930:                if (inserting)
1931:                    insertStatement.setShort(columnIndex, x);
1932:                else {
1933:                    checkUpdateFlagAndPrepareUpdateIfNeeded();
1934:                    updateStatement.setShort(columnIndex, x);
1935:                }
1936:
1937:                tempRow[columnIndex - 1] = new Short(x);
1938:            }
1939:
1940:            /**
1941:             * JDBC 2.0 Update a column with an integer value. The updateXXX() methods are
1942:             * used to update column values in the current row, or the insert row. The
1943:             * updateXXX() methods do not update the underlying database, instead the
1944:             * updateRow() or insertRow() methods are called to update the database.
1945:             * 
1946:             * @param columnIndex the first column is 1, the second is 2, ...
1947:             * @param x the new column value
1948:             * @exception SQLException if a database-access error occurs
1949:             */
1950:            public void updateInt(int columnIndex, int x) throws SQLException {
1951:                checkIfClosed();
1952:
1953:                if (inserting)
1954:                    insertStatement.setInt(columnIndex, x);
1955:                else {
1956:                    checkUpdateFlagAndPrepareUpdateIfNeeded();
1957:                    updateStatement.setInt(columnIndex, x);
1958:                }
1959:
1960:                tempRow[columnIndex - 1] = new Integer(x);
1961:            }
1962:
1963:            /**
1964:             * JDBC 2.0 Update a column with a long value. The updateXXX() methods are
1965:             * used to update column values in the current row, or the insert row. The
1966:             * updateXXX() methods do not update the underlying database, instead the
1967:             * updateRow() or insertRow() methods are called to update the database.
1968:             * 
1969:             * @param columnIndex the first column is 1, the second is 2, ...
1970:             * @param x the new column value
1971:             * @exception SQLException if a database-access error occurs
1972:             */
1973:            public void updateLong(int columnIndex, long x) throws SQLException {
1974:                checkIfClosed();
1975:
1976:                if (inserting)
1977:                    insertStatement.setLong(columnIndex, x);
1978:                else {
1979:                    checkUpdateFlagAndPrepareUpdateIfNeeded();
1980:                    updateStatement.setLong(columnIndex, x);
1981:                }
1982:
1983:                tempRow[columnIndex - 1] = new Long(x);
1984:            }
1985:
1986:            /**
1987:             * JDBC 2.0 Update a column with a float value. The updateXXX() methods are
1988:             * used to update column values in the current row, or the insert row. The
1989:             * updateXXX() methods do not update the underlying database, instead the
1990:             * updateRow() or insertRow() methods are called to update the database.
1991:             * 
1992:             * @param columnIndex the first column is 1, the second is 2, ...
1993:             * @param x the new column value
1994:             * @exception SQLException if a database-access error occurs
1995:             */
1996:            public void updateFloat(int columnIndex, float x)
1997:                    throws SQLException {
1998:                checkIfClosed();
1999:
2000:                if (inserting)
2001:                    insertStatement.setFloat(columnIndex, x);
2002:                else {
2003:                    checkUpdateFlagAndPrepareUpdateIfNeeded();
2004:                    updateStatement.setFloat(columnIndex, x);
2005:                }
2006:
2007:                tempRow[columnIndex - 1] = new Float(x);
2008:            }
2009:
2010:            /**
2011:             * JDBC 2.0 Update a column with a Double value. The updateXXX() methods are
2012:             * used to update column values in the current row, or the insert row. The
2013:             * updateXXX() methods do not update the underlying database, instead the
2014:             * updateRow() or insertRow() methods are called to update the database.
2015:             * 
2016:             * @param columnIndex the first column is 1, the second is 2, ...
2017:             * @param x the new column value
2018:             * @exception SQLException if a database-access error occurs
2019:             */
2020:            public void updateDouble(int columnIndex, double x)
2021:                    throws SQLException {
2022:                checkIfClosed();
2023:
2024:                if (inserting)
2025:                    insertStatement.setDouble(columnIndex, x);
2026:                else {
2027:                    checkUpdateFlagAndPrepareUpdateIfNeeded();
2028:                    updateStatement.setDouble(columnIndex, x);
2029:                }
2030:
2031:                tempRow[columnIndex - 1] = new Double(x);
2032:            }
2033:
2034:            /**
2035:             * JDBC 2.0 Update a column with a BigDecimal value. The updateXXX() methods
2036:             * are used to update column values in the current row, or the insert row. The
2037:             * updateXXX() methods do not update the underlying database, instead the
2038:             * updateRow() or insertRow() methods are called to update the database.
2039:             * 
2040:             * @param columnIndex the first column is 1, the second is 2, ...
2041:             * @param x the new column value
2042:             * @exception SQLException if a database-access error occurs
2043:             */
2044:            public void updateBigDecimal(int columnIndex, BigDecimal x)
2045:                    throws SQLException {
2046:                checkIfClosed();
2047:
2048:                if (inserting)
2049:                    insertStatement.setBigDecimal(columnIndex, x);
2050:                else {
2051:                    checkUpdateFlagAndPrepareUpdateIfNeeded();
2052:                    updateStatement.setBigDecimal(columnIndex, x);
2053:                }
2054:
2055:                tempRow[columnIndex - 1] = x;
2056:            }
2057:
2058:            /**
2059:             * JDBC 2.0 Update a column with a String value. The updateXXX() methods are
2060:             * used to update column values in the current row, or the insert row. The
2061:             * updateXXX() methods do not update the underlying database, instead the
2062:             * updateRow() or insertRow() methods are called to update the database.
2063:             * 
2064:             * @param columnIndex the first column is 1, the second is 2, ...
2065:             * @param x the new column value
2066:             * @exception SQLException if a database-access error occurs
2067:             */
2068:            public void updateString(int columnIndex, String x)
2069:                    throws SQLException {
2070:                checkIfClosed();
2071:
2072:                if (inserting)
2073:                    insertStatement.setString(columnIndex, x);
2074:                else {
2075:                    checkUpdateFlagAndPrepareUpdateIfNeeded();
2076:                    updateStatement.setString(columnIndex, x);
2077:                }
2078:
2079:                tempRow[columnIndex - 1] = x;
2080:            }
2081:
2082:            /**
2083:             * JDBC 2.0 Update a column with a byte array value. The updateXXX() methods
2084:             * are used to update column values in the current row, or the insert row. The
2085:             * updateXXX() methods do not update the underlying database, instead the
2086:             * updateRow() or insertRow() methods are called to update the database.
2087:             * 
2088:             * @param columnIndex the first column is 1, the second is 2, ...
2089:             * @param x the new column value
2090:             * @exception SQLException if a database-access error occurs
2091:             */
2092:            public void updateBytes(int columnIndex, byte[] x)
2093:                    throws SQLException {
2094:                checkIfClosed();
2095:
2096:                if (inserting)
2097:                    insertStatement.setBytes(columnIndex, x);
2098:                else {
2099:                    checkUpdateFlagAndPrepareUpdateIfNeeded();
2100:                    updateStatement.setBytes(columnIndex, x);
2101:                }
2102:
2103:                tempRow[columnIndex - 1] = x;
2104:            }
2105:
2106:            /**
2107:             * JDBC 2.0 Update a column with a Date value. The updateXXX() methods are
2108:             * used to update column values in the current row, or the insert row. The
2109:             * updateXXX() methods do not update the underlying database, instead the
2110:             * updateRow() or insertRow() methods are called to update the database.
2111:             * 
2112:             * @param columnIndex the first column is 1, the second is 2, ...
2113:             * @param x the new column value
2114:             * @exception SQLException if a database-access error occurs
2115:             */
2116:            public void updateDate(int columnIndex, java.sql.Date x)
2117:                    throws SQLException {
2118:                checkIfClosed();
2119:
2120:                if (inserting)
2121:                    insertStatement.setDate(columnIndex, x);
2122:                else {
2123:                    checkUpdateFlagAndPrepareUpdateIfNeeded();
2124:                    updateStatement.setDate(columnIndex, x);
2125:                }
2126:
2127:                tempRow[columnIndex - 1] = x;
2128:            }
2129:
2130:            /**
2131:             * JDBC 2.0 Update a column with a Time value. The updateXXX() methods are
2132:             * used to update column values in the current row, or the insert row. The
2133:             * updateXXX() methods do not update the underlying database, instead the
2134:             * updateRow() or insertRow() methods are called to update the database.
2135:             * 
2136:             * @param columnIndex the first column is 1, the second is 2, ...
2137:             * @param x the new column value
2138:             * @exception SQLException if a database-access error occurs
2139:             */
2140:            public void updateTime(int columnIndex, java.sql.Time x)
2141:                    throws SQLException {
2142:                checkIfClosed();
2143:
2144:                if (inserting)
2145:                    insertStatement.setTime(columnIndex, x);
2146:                else {
2147:                    checkUpdateFlagAndPrepareUpdateIfNeeded();
2148:                    updateStatement.setTime(columnIndex, x);
2149:                }
2150:
2151:                tempRow[columnIndex - 1] = x;
2152:            }
2153:
2154:            /**
2155:             * JDBC 2.0 Update a column with a Timestamp value. The updateXXX() methods
2156:             * are used to update column values in the current row, or the insert row. The
2157:             * updateXXX() methods do not update the underlying database, instead the
2158:             * updateRow() or insertRow() methods are called to update the database.
2159:             * 
2160:             * @param columnIndex the first column is 1, the second is 2, ...
2161:             * @param x the new column value
2162:             * @exception SQLException if a database-access error occurs
2163:             */
2164:            public void updateTimestamp(int columnIndex, java.sql.Timestamp x)
2165:                    throws SQLException {
2166:                checkIfClosed();
2167:
2168:                if (inserting)
2169:                    insertStatement.setTimestamp(columnIndex, x);
2170:                else {
2171:                    checkUpdateFlagAndPrepareUpdateIfNeeded();
2172:                    updateStatement.setTimestamp(columnIndex, x);
2173:                }
2174:
2175:                tempRow[columnIndex - 1] = x;
2176:            }
2177:
2178:            /**
2179:             * JDBC 2.0 Update a column with an ascii stream value. The updateXXX()
2180:             * methods are used to update column values in the current row, or the insert
2181:             * row. The updateXXX() methods do not update the underlying database, instead
2182:             * the updateRow() or insertRow() methods are called to update the database.
2183:             * 
2184:             * @param columnIndex the first column is 1, the second is 2, ...
2185:             * @param x the new column value
2186:             * @param length the length of the stream
2187:             * @exception SQLException if a database-access error occurs
2188:             */
2189:            public void updateAsciiStream(int columnIndex,
2190:                    java.io.InputStream x, int length) throws SQLException {
2191:                this .updateBinaryStream(columnIndex, x, length);
2192:            }
2193:
2194:            /**
2195:             * JDBC 2.0 Update a column with a binary stream value. The updateXXX()
2196:             * methods are used to update column values in the current row, or the insert
2197:             * row. The updateXXX() methods do not update the underlying database, instead
2198:             * the updateRow() or insertRow() methods are called to update the database.
2199:             * 
2200:             * @param columnIndex the first column is 1, the second is 2, ...
2201:             * @param x the new column value
2202:             * @param length the length of the stream
2203:             * @exception SQLException if a database-access error occurs
2204:             */
2205:            public void updateBinaryStream(int columnIndex,
2206:                    java.io.InputStream x, int length) throws SQLException {
2207:                checkIfClosed();
2208:
2209:                byte[] content = new byte[length];
2210:                try {
2211:                    x.read(content, 0, length);
2212:                } catch (Exception ioe) {
2213:                    throw new SQLException("Problem with streaming of data");
2214:                }
2215:
2216:                this .updateBytes(columnIndex, content);
2217:            }
2218:
2219:            /**
2220:             * JDBC 2.0 Update a column with a character stream value. The updateXXX()
2221:             * methods are used to update column values in the current row, or the insert
2222:             * row. The updateXXX() methods do not update the underlying database, instead
2223:             * the updateRow() or insertRow() methods are called to update the database.
2224:             * 
2225:             * @param columnIndex the first column is 1, the second is 2, ...
2226:             * @param x the new column value
2227:             * @param length the length of the stream
2228:             * @exception SQLException if a database-access error occurs
2229:             */
2230:            public void updateCharacterStream(int columnIndex,
2231:                    java.io.Reader x, int length) throws SQLException {
2232:                checkIfClosed();
2233:
2234:                char[] content = new char[length];
2235:                try {
2236:                    x.read(content, 0, length);
2237:                } catch (Exception ioe) {
2238:                    throw new SQLException("Problem with streaming of data");
2239:                }
2240:
2241:                this .updateString(columnIndex, new String(content));
2242:            }
2243:
2244:            /**
2245:             * JDBC 2.0 Update a column with an Object value. The updateXXX() methods are
2246:             * used to update column values in the current row, or the insert row. The
2247:             * updateXXX() methods do not update the underlying database, instead the
2248:             * updateRow() or insertRow() methods are called to update the database.
2249:             * 
2250:             * @param columnIndex the first column is 1, the second is 2, ...
2251:             * @param x the new column value
2252:             * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
2253:             *          this is the number of digits after the decimal. For all other
2254:             *          types this value will be ignored.
2255:             * @exception SQLException if a database-access error occurs
2256:             */
2257:            public void updateObject(int columnIndex, Object x, int scale)
2258:                    throws SQLException {
2259:                checkIfClosed();
2260:
2261:                if (inserting)
2262:                    insertStatement.setObject(columnIndex, x, scale);
2263:                else {
2264:                    checkUpdateFlagAndPrepareUpdateIfNeeded();
2265:                    updateStatement.setObject(columnIndex, x, scale);
2266:                }
2267:
2268:                tempRow[columnIndex - 1] = x;
2269:            }
2270:
2271:            /**
2272:             * JDBC 2.0 Update a column with an Object value. The updateXXX() methods are
2273:             * used to update column values in the current row, or the insert row. The
2274:             * updateXXX() methods do not update the underlying database, instead the
2275:             * updateRow() or insertRow() methods are called to update the database.
2276:             * 
2277:             * @param columnIndex the first column is 1, the second is 2, ...
2278:             * @param x the new column value
2279:             * @exception SQLException if a database-access error occurs
2280:             */
2281:            public void updateObject(int columnIndex, Object x)
2282:                    throws SQLException {
2283:                checkIfClosed();
2284:
2285:                if (inserting)
2286:                    insertStatement.setObject(columnIndex, x);
2287:                else {
2288:                    checkUpdateFlagAndPrepareUpdateIfNeeded();
2289:                    updateStatement.setObject(columnIndex, x);
2290:                }
2291:
2292:                tempRow[columnIndex - 1] = x;
2293:            }
2294:
2295:            /**
2296:             * JDBC 2.0 Update a column with a null value. The updateXXX() methods are
2297:             * used to update column values in the current row, or the insert row. The
2298:             * updateXXX() methods do not update the underlying database, instead the
2299:             * updateRow() or insertRow() methods are called to update the database.
2300:             * 
2301:             * @param columnName the name of the column
2302:             * @exception SQLException if a database-access error occurs
2303:             */
2304:
2305:            public void updateNull(String columnName) throws SQLException {
2306:                this .updateNull(findColumn(columnName));
2307:            }
2308:
2309:            /**
2310:             * JDBC 2.0 Update a column with a boolean value. The updateXXX() methods are
2311:             * used to update column values in the current row, or the insert row. The
2312:             * updateXXX() methods do not update the underlying database, instead the
2313:             * updateRow() or insertRow() methods are called to update the database.
2314:             * 
2315:             * @param columnName the name of the column
2316:             * @param x the new column value
2317:             * @exception SQLException if a database-access error occurs
2318:             */
2319:            public void updateBoolean(String columnName, boolean x)
2320:                    throws SQLException {
2321:                this .updateBoolean(findColumn(columnName), x);
2322:            }
2323:
2324:            /**
2325:             * JDBC 2.0 Update a column with a byte value. The updateXXX() methods are
2326:             * used to update column values in the current row, or the insert row. The
2327:             * updateXXX() methods do not update the underlying database, instead the
2328:             * updateRow() or insertRow() methods are called to update the database.
2329:             * 
2330:             * @param columnName the name of the column
2331:             * @param x the new column value
2332:             * @exception SQLException if a database-access error occurs
2333:             */
2334:            public void updateByte(String columnName, byte x)
2335:                    throws SQLException {
2336:                this .updateByte(findColumn(columnName), x);
2337:            }
2338:
2339:            /**
2340:             * JDBC 2.0 Update a column with a short value. The updateXXX() methods are
2341:             * used to update column values in the current row, or the insert row. The
2342:             * updateXXX() methods do not update the underlying database, instead the
2343:             * updateRow() or insertRow() methods are called to update the database.
2344:             * 
2345:             * @param columnName the name of the column
2346:             * @param x the new column value
2347:             * @exception SQLException if a database-access error occurs
2348:             */
2349:            public void updateShort(String columnName, short x)
2350:                    throws SQLException {
2351:                this .updateShort(findColumn(columnName), x);
2352:            }
2353:
2354:            /**
2355:             * JDBC 2.0 Update a column with an integer value. The updateXXX() methods are
2356:             * used to update column values in the current row, or the insert row. The
2357:             * updateXXX() methods do not update the underlying database, instead the
2358:             * updateRow() or insertRow() methods are called to update the database.
2359:             * 
2360:             * @param columnName the name of the column
2361:             * @param x the new column value
2362:             * @exception SQLException if a database-access error occurs
2363:             */
2364:            public void updateInt(String columnName, int x) throws SQLException {
2365:                this .updateInt(findColumn(columnName), x);
2366:            }
2367:
2368:            /**
2369:             * JDBC 2.0 Update a column with a long value. The updateXXX() methods are
2370:             * used to update column values in the current row, or the insert row. The
2371:             * updateXXX() methods do not update the underlying database, instead the
2372:             * updateRow() or insertRow() methods are called to update the database.
2373:             * 
2374:             * @param columnName the name of the column
2375:             * @param x the new column value
2376:             * @exception SQLException if a database-access error occurs
2377:             */
2378:            public void updateLong(String columnName, long x)
2379:                    throws SQLException {
2380:                this .updateLong(findColumn(columnName), x);
2381:            }
2382:
2383:            /**
2384:             * JDBC 2.0 Update a column with a float value. The updateXXX() methods are
2385:             * used to update column values in the current row, or the insert row. The
2386:             * updateXXX() methods do not update the underlying database, instead the
2387:             * updateRow() or insertRow() methods are called to update the database.
2388:             * 
2389:             * @param columnName the name of the column
2390:             * @param x the new column value
2391:             * @exception SQLException if a database-access error occurs
2392:             */
2393:            public void updateFloat(String columnName, float x)
2394:                    throws SQLException {
2395:                this .updateFloat(findColumn(columnName), x);
2396:            }
2397:
2398:            /**
2399:             * JDBC 2.0 Update a column with a double value. The updateXXX() methods are
2400:             * used to update column values in the current row, or the insert row. The
2401:             * updateXXX() methods do not update the underlying database, instead the
2402:             * updateRow() or insertRow() methods are called to update the database.
2403:             * 
2404:             * @param columnName the name of the column
2405:             * @param x the new column value
2406:             * @exception SQLException if a database-access error occurs
2407:             */
2408:            public void updateDouble(String columnName, double x)
2409:                    throws SQLException {
2410:                this .updateDouble(findColumn(columnName), x);
2411:            }
2412:
2413:            /**
2414:             * JDBC 2.0 Update a column with a BigDecimal value. The updateXXX() methods
2415:             * are used to update column values in the current row, or the insert row. The
2416:             * updateXXX() methods do not update the underlying database, instead the
2417:             * updateRow() or insertRow() methods are called to update the database.
2418:             * 
2419:             * @param columnName the name of the column
2420:             * @param x the new column value
2421:             * @exception SQLException if a database-access error occurs
2422:             */
2423:            public void updateBigDecimal(String columnName, BigDecimal x)
2424:                    throws SQLException {
2425:                this .updateBigDecimal(findColumn(columnName), x);
2426:            }
2427:
2428:            /**
2429:             * JDBC 2.0 Update a column with a String value. The updateXXX() methods are
2430:             * used to update column values in the current row, or the insert row. The
2431:             * updateXXX() methods do not update the underlying database, instead the
2432:             * updateRow() or insertRow() methods are called to update the database.
2433:             * 
2434:             * @param columnName the name of the column
2435:             * @param x the new column value
2436:             * @exception SQLException if a database-access error occurs
2437:             */
2438:            public void updateString(String columnName, String x)
2439:                    throws SQLException {
2440:                this .updateString(findColumn(columnName), x);
2441:            }
2442:
2443:            /**
2444:             * JDBC 2.0 Update a column with a byte array value. The updateXXX() methods
2445:             * are used to update column values in the current row, or the insert row. The
2446:             * updateXXX() methods do not update the underlying database, instead the
2447:             * updateRow() or insertRow() methods are called to update the database.
2448:             * 
2449:             * @param columnName the name of the column
2450:             * @param x the new column value
2451:             * @exception SQLException if a database-access error occurs
2452:             */
2453:            public void updateBytes(String columnName, byte[] x)
2454:                    throws SQLException {
2455:                this .updateBytes(findColumn(columnName), x);
2456:            }
2457:
2458:            /**
2459:             * JDBC 2.0 Update a column with a Date value. The updateXXX() methods are
2460:             * used to update column values in the current row, or the insert row. The
2461:             * updateXXX() methods do not update the underlying database, instead the
2462:             * updateRow() or insertRow() methods are called to update the database.
2463:             * 
2464:             * @param columnName the name of the column
2465:             * @param x the new column value
2466:             * @exception SQLException if a database-access error occurs
2467:             */
2468:            public void updateDate(String columnName, java.sql.Date x)
2469:                    throws SQLException {
2470:                this .updateDate(findColumn(columnName), x);
2471:            }
2472:
2473:            /**
2474:             * JDBC 2.0 Update a column with a Time value. The updateXXX() methods are
2475:             * used to update column values in the current row, or the insert row. The
2476:             * updateXXX() methods do not update the underlying database, instead the
2477:             * updateRow() or insertRow() methods are called to update the database.
2478:             * 
2479:             * @param columnName the name of the column
2480:             * @param x the new column value
2481:             * @exception SQLException if a database-access error occurs
2482:             */
2483:            public void updateTime(String columnName, java.sql.Time x)
2484:                    throws SQLException {
2485:                this .updateTime(findColumn(columnName), x);
2486:            }
2487:
2488:            /**
2489:             * JDBC 2.0 Update a column with a Timestamp value. The updateXXX() methods
2490:             * are used to update column values in the current row, or the insert row. The
2491:             * updateXXX() methods do not update the underlying database, instead the
2492:             * updateRow() or insertRow() methods are called to update the database.
2493:             * 
2494:             * @param columnName the name of the column
2495:             * @param x the new column value
2496:             * @exception SQLException if a database-access error occurs
2497:             */
2498:            public void updateTimestamp(String columnName, java.sql.Timestamp x)
2499:                    throws SQLException {
2500:                this .updateTimestamp(findColumn(columnName), x);
2501:            }
2502:
2503:            /**
2504:             * JDBC 2.0 Update a column with an ascii stream value. The updateXXX()
2505:             * methods are used to update column values in the current row, or the insert
2506:             * row. The updateXXX() methods do not update the underlying database, instead
2507:             * the updateRow() or insertRow() methods are called to update the database.
2508:             * 
2509:             * @param columnName the name of the column
2510:             * @param x the new column value
2511:             * @param length of the stream
2512:             * @exception SQLException if a database-access error occurs
2513:             */
2514:            public void updateAsciiStream(String columnName,
2515:                    java.io.InputStream x, int length) throws SQLException {
2516:                this .updateAsciiStream(findColumn(columnName), x, length);
2517:            }
2518:
2519:            /**
2520:             * JDBC 2.0 Update a column with a binary stream value. The updateXXX()
2521:             * methods are used to update column values in the current row, or the insert
2522:             * row. The updateXXX() methods do not update the underlying database, instead
2523:             * the updateRow() or insertRow() methods are called to update the database.
2524:             * 
2525:             * @param columnName the name of the column
2526:             * @param x the new column value
2527:             * @param length of the stream
2528:             * @exception SQLException if a database-access error occurs
2529:             */
2530:            public void updateBinaryStream(String columnName,
2531:                    java.io.InputStream x, int length) throws SQLException {
2532:                this .updateBinaryStream(findColumn(columnName), x, length);
2533:            }
2534:
2535:            /**
2536:             * JDBC 2.0 Update a column with a character stream value. The updateXXX()
2537:             * methods are used to update column values in the current row, or the insert
2538:             * row. The updateXXX() methods do not update the underlying database, instead
2539:             * the updateRow() or insertRow() methods are called to update the database.
2540:             * 
2541:             * @param columnName the name of the column
2542:             * @param reader the stream
2543:             * @param length of the stream
2544:             * @exception SQLException if a database-access error occurs
2545:             */
2546:            public void updateCharacterStream(String columnName,
2547:                    java.io.Reader reader, int length) throws SQLException {
2548:                this .updateCharacterStream(findColumn(columnName), reader,
2549:                        length);
2550:            }
2551:
2552:            /**
2553:             * JDBC 2.0 Update a column with an Object value. The updateXXX() methods are
2554:             * used to update column values in the current row, or the insert row. The
2555:             * updateXXX() methods do not update the underlying database, instead the
2556:             * updateRow() or insertRow() methods are called to update the database.
2557:             * 
2558:             * @param columnName the name of the column
2559:             * @param x the new column value
2560:             * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
2561:             *          this is the number of digits after the decimal. For all other
2562:             *          types this value will be ignored.
2563:             * @exception SQLException if a database-access error occurs
2564:             */
2565:            public void updateObject(String columnName, Object x, int scale)
2566:                    throws SQLException {
2567:                this .updateObject(findColumn(columnName), x, scale);
2568:            }
2569:
2570:            /**
2571:             * JDBC 2.0 Update a column with an Object value. The updateXXX() methods are
2572:             * used to update column values in the current row, or the insert row. The
2573:             * updateXXX() methods do not update the underlying database, instead the
2574:             * updateRow() or insertRow() methods are called to update the database.
2575:             * 
2576:             * @param columnName the name of the column
2577:             * @param x the new column value
2578:             * @exception SQLException if a database-access error occurs
2579:             */
2580:            public void updateObject(String columnName, Object x)
2581:                    throws SQLException {
2582:                this .updateObject(findColumn(columnName), x);
2583:            }
2584:
2585:            /**
2586:             * JDBC 2.0 Insert the contents of the insert row into the result set and the
2587:             * database. Must be on the insert row when this method is called.
2588:             * 
2589:             * @exception SQLException if a database-access error occurs, if called when
2590:             *              not on the insert row, or if all non-nullable columns in the
2591:             *              insert row have not been given a value
2592:             */
2593:            public void insertRow() throws SQLException {
2594:                checkIfClosed();
2595:
2596:                if (!inserting)
2597:                    throw new SQLException("insertRow cannot be called "
2598:                            + "when the cursor is not on the insert row");
2599:
2600:                // Insert row in underlying database
2601:                try {
2602:                    insertStatement.executeUpdate();
2603:                } finally {
2604:                    // Clean up
2605:                    insertStatement.clearParameters();
2606:                }
2607:
2608:                // Insert row in this ResultSet
2609:                if (data == null)
2610:                    data = new ArrayList();
2611:                data.add(tempRow);
2612:                nbOfRows++;
2613:
2614:                // Prepare for a new insert
2615:                tempRow = new Object[nbOfColumns];
2616:            }
2617:
2618:            /**
2619:             * JDBC 2.0 Update the underlying database with the new contents of the
2620:             * current row. Cannot be called when on the insert row.
2621:             * 
2622:             * @exception SQLException if a database-access error occurs, or if called
2623:             *              when on the insert row
2624:             */
2625:            public void updateRow() throws SQLException {
2626:                checkIfClosed();
2627:
2628:                if (inserting)
2629:                    throw new SQLException("updateRow cannot be called "
2630:                            + "when the cursor is on the insert row");
2631:
2632:                if (!updating)
2633:                    return;
2634:
2635:                // Add primary key info from current row
2636:                for (int i = 0; i < primaryKeyColumns.length; ++i)
2637:                    updateStatement
2638:                            .setObject(
2639:                                    nbOfColumns + i + 1,
2640:                                    ((Object[]) data.get(currentRow))[findColumn(primaryKeyColumns[i]) - 1]);
2641:
2642:                // Update row in underlying database
2643:                try {
2644:                    updateStatement.executeUpdate();
2645:                } finally {
2646:                    // Clean up
2647:                    updateStatement.clearParameters();
2648:                }
2649:
2650:                // Update row in this ResultSet
2651:                data.set(currentRow, tempRow);
2652:
2653:                // Clean up
2654:                tempRow = null;
2655:                updating = false;
2656:            }
2657:
2658:            /**
2659:             * JDBC 2.0 Delete the current row from the result set and the underlying
2660:             * database. Cannot be called when on the insert row.
2661:             * 
2662:             * @exception SQLException if a database-access error occurs, or if called
2663:             *              when on the insert row.
2664:             */
2665:            public void deleteRow() throws SQLException {
2666:                checkIfClosed();
2667:
2668:                if (inserting)
2669:                    throw new SQLException("deleteRow cannot be called "
2670:                            + "when the cursor is on the insert row");
2671:
2672:                this .checkRowPos();
2673:
2674:                if (deleteStatement == null)
2675:                    this .buildDeleteStatement();
2676:
2677:                // Add primary key info from current row
2678:                for (int i = 0; i < primaryKeyColumns.length; ++i)
2679:                    deleteStatement
2680:                            .setObject(
2681:                                    i + 1,
2682:                                    ((Object[]) data.get(currentRow))[findColumn(primaryKeyColumns[i]) - 1]);
2683:
2684:                // Delete row from underlying database
2685:                try {
2686:                    deleteStatement.executeUpdate();
2687:                } finally {
2688:                    // Clean up
2689:                    deleteStatement.clearParameters();
2690:                }
2691:
2692:                // Delete row from this ResultSet
2693:                data.remove(currentRow);
2694:                nbOfRows--;
2695:
2696:                // Deleting cancels all updates on the row
2697:                if (updating)
2698:                    this .cancelRowUpdates();
2699:            }
2700:
2701:            /**
2702:             * JDBC 2.0 Refresh the value of the current row with its current value in the
2703:             * database. Cannot be called when on the insert row. The refreshRow() method
2704:             * provides a way for an application to explicitly tell the JDBC driver to
2705:             * refetch a row(s) from the database. An application may want to call
2706:             * refreshRow() when caching or prefetching is being done by the JDBC driver
2707:             * to fetch the latest value of a row from the database. The JDBC driver may
2708:             * actually refresh multiple rows at once if the fetch size is greater than
2709:             * one. All values are refetched subject to the transaction isolation level
2710:             * and cursor sensitivity. If refreshRow() is called after calling
2711:             * updateXXX(), but before calling updateRow() then the updates made to the
2712:             * row are lost. Calling refreshRow() frequently will likely slow performance.
2713:             * 
2714:             * @exception SQLException if a database-access error occurs, or if called
2715:             *              when on the insert row.
2716:             */
2717:            public void refreshRow() throws SQLException {
2718:                checkIfClosed();
2719:
2720:                if (inserting)
2721:                    throw new SQLException("refreshRow cannot be called "
2722:                            + "when the cursor is on the insert row");
2723:
2724:                this .checkRowPos();
2725:
2726:                if (refreshStatement == null)
2727:                    this .buildRefreshStatement();
2728:
2729:                // Add primary key info from current row
2730:                for (int i = 0; i < primaryKeyColumns.length; ++i)
2731:                    refreshStatement
2732:                            .setObject(
2733:                                    i + 1,
2734:                                    ((Object[]) data.get(currentRow))[findColumn(primaryKeyColumns[i]) - 1]);
2735:
2736:                // Retrieve row from underlying database
2737:                DriverResultSet res;
2738:                try {
2739:                    res = (DriverResultSet) refreshStatement.executeQuery();
2740:                } finally {
2741:                    // Clean up
2742:                    refreshStatement.clearParameters();
2743:                }
2744:
2745:                // Refresh row in this ResultSet
2746:                try {
2747:                    data.set(currentRow, res.data.get(0));
2748:                } catch (NullPointerException e) {
2749:                    throw new SQLException("The current row has been "
2750:                            + "removed from the database");
2751:                } finally {
2752:                    // Clean up
2753:                    res.close();
2754:                }
2755:
2756:                // Refreshing cancels all updates on the row
2757:                if (updating)
2758:                    this .cancelRowUpdates();
2759:            }
2760:
2761:            /**
2762:             * JDBC 2.0 The cancelRowUpdates() method may be called after calling an
2763:             * updateXXX() method(s) and before calling updateRow() to rollback the
2764:             * updates made to a row. If no updates have been made or updateRow() has
2765:             * already been called, then this method has no effect.
2766:             * 
2767:             * @exception SQLException if a database-access error occurs, or if called
2768:             *              when on the insert row.
2769:             */
2770:            public void cancelRowUpdates() throws SQLException {
2771:                checkIfClosed();
2772:
2773:                if (inserting)
2774:                    throw new SQLException("cancelRowUpdates cannot be "
2775:                            + "called when the cursor is on the insert row");
2776:
2777:                if (!updating)
2778:                    return;
2779:
2780:                updateStatement.clearParameters();
2781:                tempRow = null;
2782:                updating = false;
2783:            }
2784:
2785:            /**
2786:             * JDBC 2.0 Move to the insert row. The current cursor position is remembered
2787:             * while the cursor is positioned on the insert row. The insert row is a
2788:             * special row associated with an updatable result set. It is essentially a
2789:             * buffer where a new row may be constructed by calling the updateXXX()
2790:             * methods prior to inserting the row into the result set. Only the
2791:             * updateXXX(), getXXX(), and insertRow() methods may be called when the
2792:             * cursor is on the insert row. All of the columns in a result set must be
2793:             * given a value each time this method is called before calling insertRow().
2794:             * UpdateXXX()must be called before getXXX() on a column.
2795:             * 
2796:             * @exception SQLException if a database-access error occurs, or the result
2797:             *              set is not updatable
2798:             */
2799:            public void moveToInsertRow() throws SQLException {
2800:                checkIfClosed();
2801:
2802:                if (inserting)
2803:                    return;
2804:
2805:                if (insertStatement == null)
2806:                    this .buildInsertStatement();
2807:
2808:                tempRow = new Object[nbOfColumns];
2809:                inserting = true;
2810:            }
2811:
2812:            /**
2813:             * JDBC 2.0 Move the cursor to the remembered cursor position, usually the
2814:             * current row. Has no effect unless the cursor is on the insert row.
2815:             * 
2816:             * @exception SQLException if a database-access error occurs, or the result
2817:             *              set is not updatable
2818:             */
2819:            public void moveToCurrentRow() throws SQLException {
2820:                checkIfClosed();
2821:
2822:                if (!inserting)
2823:                    return;
2824:
2825:                insertStatement.clearParameters();
2826:                tempRow = null;
2827:                inserting = false;
2828:            }
2829:
2830:            //
2831:            // ------------------------------------------
2832:            // ResultSet meta-data related functions
2833:            // ------------------------------------------
2834:            //
2835:
2836:            /**
2837:             * JDBC 2.0 Return the type of this result set. The type is determined based
2838:             * on the statement that created the result set.
2839:             * 
2840:             * @return TYPE_FORWARD_ONLY, TYPE_SCROLL_INSENSITIVE, or
2841:             *         TYPE_SCROLL_SENSITIVE
2842:             * @exception SQLException if a database-access error occurs
2843:             */
2844:            public int getType() throws SQLException {
2845:                return resultSetType;
2846:            }
2847:
2848:            /**
2849:             * JDBC 2.0 Return the concurrency of this result set. The concurrency used is
2850:             * determined by the statement that created the result set.
2851:             * 
2852:             * @return CONCUR_READ_ONLY or CONCUR_UPDATABLE
2853:             * @exception SQLException if a database-access error occurs
2854:             */
2855:
2856:            public int getConcurrency() throws SQLException {
2857:                return resultSetConcurrency;
2858:            }
2859:
2860:            /**
2861:             * Closes the remote ResultSet if the ResultSet was streamed else just closes
2862:             * the ResultSet locally.
2863:             * 
2864:             * @exception SQLException if a database access error occurs
2865:             */
2866:            public void close() throws SQLException {
2867:                if (isClosed)
2868:                    return;
2869:
2870:                closeCurrentStreamIfExists();
2871:
2872:                if (hasMoreData)
2873:                    this .connection.closeRemoteResultSet(cursorName);
2874:                isClosed = true;
2875:                // garbage collect some data
2876:                this .data = null;
2877:                this .fields = null;
2878:                this .owningStatement = null;
2879:                this .warnings = null;
2880:            }
2881:
2882:            /**
2883:             * A column may have the value of SQL NULL; wasNull() reports whether the last
2884:             * column read had this special value. Note that you must first call getXXX on
2885:             * a column to try to read its value and then call wasNull() to find if the
2886:             * value was SQL NULL
2887:             * 
2888:             * @return <code>true</code> if the last column read was SQL NULL
2889:             * @exception SQLException if a database access error occurred
2890:             */
2891:
2892:            public boolean wasNull() throws SQLException {
2893:                return wasNullFlag;
2894:            }
2895:
2896:            /**
2897:             * JDBC 2.0 Return the <code>Statement</code> that produced the
2898:             * <code>ResultSet</code>.
2899:             * 
2900:             * @return the <code>Statement</code> that produced the
2901:             *         <code>ResultSet</code>, or null if the result was produced some
2902:             *         other way.
2903:             * @exception SQLException if a database-access error occurs
2904:             */
2905:            public java.sql.Statement getStatement() throws SQLException {
2906:                return owningStatement;
2907:            }
2908:
2909:            /**
2910:             * Set the hasMoreData boolean (is there more data to fetch from the
2911:             * controller). This function is used by the ResultSet streaming feature.
2912:             * 
2913:             * @param hasMore new value for hasMoreData
2914:             */
2915:            public void setHasMoreData(boolean hasMore) {
2916:                hasMoreData = hasMore;
2917:            }
2918:
2919:            /**
2920:             * The numbers, types and properties of a <code>ResultSet</code>'s columns
2921:             * are provided by the <code>getMetaData</code> method
2922:             * 
2923:             * @return a description of the <code>ResultSet</code>'s columns
2924:             * @exception SQLException if a database access error occurs
2925:             */
2926:            public java.sql.ResultSetMetaData getMetaData() throws SQLException {
2927:                return new ResultSetMetaData(this );
2928:            }
2929:
2930:            /**
2931:             * Map a <code>ResultSet</code> column name to a <code>ResultSet</code>
2932:             * column index
2933:             * 
2934:             * @param columnName the name of the column
2935:             * @return the column index
2936:             * @exception SQLException if a database access error occurs
2937:             */
2938:            public int findColumn(String columnName) throws SQLException {
2939:                if (columnName == null)
2940:                    throw new java.sql.SQLException("Invalid null column name");
2941:
2942:                checkIfClosed();
2943:
2944:                Integer index;
2945:
2946:                // Try to match the exact case (not per the spec!)
2947:                if (sensitiveNameToIndex == null) {
2948:                    sensitiveNameToIndex = new Hashtable();
2949:                    buildIndexMapping(sensitiveNameToIndex, true);
2950:                }
2951:                index = (Integer) sensitiveNameToIndex.get(columnName);
2952:                if (index != null)
2953:                    return index.intValue() + 1;
2954:
2955:                // Try to be case-insensitive (according to the spec)
2956:                if (lowerNameToIndex == null) {
2957:                    lowerNameToIndex = new Hashtable();
2958:                    buildIndexMapping(lowerNameToIndex, false);
2959:                }
2960:                index = (Integer) lowerNameToIndex
2961:                        .get(columnName.toLowerCase());
2962:                if (index != null)
2963:                    return index.intValue() + 1;
2964:
2965:                // nothing found
2966:                throw new java.sql.SQLException("Column '" + columnName
2967:                        + "' not found.");
2968:            }
2969:
2970:            // ****************************************************************
2971:            //
2972:            // END OF PUBLIC INTERFACE
2973:            //
2974:            // ****************************************************************
2975:
2976:            /**
2977:             * Creates a new <code>DriverResultSet</code> object, deserializing it from
2978:             * an input stream. MUST mirror the following serialization method
2979:             * {@link org.continuent.sequoia.controller.backend.result.ControllerResultSet#sendToStream(org.continuent.sequoia.common.stream.DriverBufferedOutputStream)}
2980:             * 
2981:             * @param conn the connection we read from and belong to
2982:             * @throws IOException if a network problem occurs
2983:             * @throws ProtocolException if a protocol error occurs
2984:             */
2985:
2986:            public DriverResultSet(Connection conn) throws IOException,
2987:                    ProtocolException {
2988:                this .connection = conn;
2989:                DriverBufferedInputStream input = this .connection.socketInput;
2990:                // Get the warning chain
2991:                if (input.readBoolean()) {
2992:                    warnings = new BackendDriverException(input);
2993:                } else
2994:                    warnings = null;
2995:                // Get the ResultSet metadata, deserialize columns information
2996:                this .nbOfColumns = input.readInt();
2997:                this .fields = new Field[nbOfColumns];
2998:                for (int f = 0; f < this .nbOfColumns; f++)
2999:                    this .fields[f] = new Field(input);
3000:
3001:                if (!TypeTag.COL_TYPES.equals(new TypeTag(input)))
3002:                    throw new ProtocolException("Column types were expected");
3003:
3004:                // This could be just a boolean, see next line. But there is no real need
3005:                // for change.
3006:                this .nbOfRows = input.readInt();
3007:
3008:                // Receive java types
3009:                if (this .nbOfRows > 0) {
3010:                    this .serializers = new SQLDataSerialization.Serializer[nbOfColumns];
3011:                    for (int col = 0; col < this .nbOfColumns; col++) {
3012:                        TypeTag tag = new TypeTag(input);
3013:                        try {
3014:                            serializers[col] = SQLDataSerialization
3015:                                    .getSerializer(tag);
3016:                        } catch (IllegalArgumentException iae) {
3017:                            ProtocolException pe = new ProtocolException(
3018:                                    "Protocol corruption: received unknown TypeTag "
3019:                                            + tag + " for column " + col);
3020:                            pe.initCause(iae);
3021:                            throw pe;
3022:                        }
3023:                    }
3024:                }
3025:
3026:                receiveRows();
3027:
3028:                if (this .hasMoreData)
3029:                    this .cursorName = input.readLongUTF();
3030:
3031:                this .isClosed = false;
3032:
3033:            }
3034:
3035:            /**
3036:             * Creates a new empty <code>DriverResultSet</code> object
3037:             * 
3038:             * @param empty MUST be true
3039:             */
3040:            DriverResultSet(Connection conn, boolean empty) {
3041:                if (!empty)
3042:                    throw new IllegalArgumentException(
3043:                            "empty flag must be true in DriverResultSet constructor");
3044:
3045:                connection = conn;
3046:                inserting = false;
3047:                updating = false;
3048:                nbOfRows = 0;
3049:                nbOfColumns = 0;
3050:                hasMoreData = false;
3051:                isClosed = false;
3052:            }
3053:
3054:            /**
3055:             * Tells the controller we don't need this ResultSet anymore (ie. closes the
3056:             * remote ResultSet)
3057:             * 
3058:             * @see #close()
3059:             */
3060:            protected void finalize() throws Throwable {
3061:                this .close();
3062:                super .finalize();
3063:            }
3064:
3065:            /**
3066:             * Creates a new <code>DriverResultSet</code> object with given data
3067:             * (currently only supports one column, because it is used only to support
3068:             * generated keys on batch update, when alwaysGetGeneratedKeys is set to true)
3069:             * 
3070:             * @param conn 
3071:             * @param fromData List of objects to be inserted in this resultset
3072:             * @param fromField Metadata for this colum
3073:             */
3074:            public DriverResultSet(Connection conn, ArrayList fromData,
3075:                    Field fromField) {
3076:                this (conn, true);
3077:                if (fromData != null && fromData.size() > 0) {
3078:                    nbOfRows = fromData.size();
3079:                    nbOfColumns = 1;
3080:                    hasMoreData = false;
3081:                    this .data = new ArrayList(this .nbOfRows);
3082:                    for (int i = 0; i < nbOfRows; i++) {
3083:                        Object[] row = new Object[nbOfColumns];
3084:                        row[0] = fromData.get(i);
3085:                        this .data.add(row);
3086:                    }
3087:                    this .fields = new Field[1];
3088:                    this .fields[0] = fromField;
3089:                }
3090:            }
3091:
3092:            /**
3093:             * De-serialize only data rows, not any metadata. Useful for streaming. This
3094:             * method MUST mirror the following serialization method:
3095:             * {@link org.continuent.sequoia.controller.backend.result.ControllerResultSet#sendRowsToStream(org.continuent.sequoia.common.stream.DriverBufferedOutputStream)}
3096:             * 
3097:             * @throws IOException stream error
3098:             * @throws ProtocolException protocol corruption
3099:             */
3100:            private void receiveRows() throws IOException, ProtocolException {
3101:
3102:                DriverBufferedInputStream input = connection.socketInput;
3103:                this .nbOfRows = input.readInt();
3104:
3105:                boolean[] nulls = new boolean[this .nbOfColumns];
3106:
3107:                // Receive the actual data
3108:                this .data = new ArrayList(this .nbOfRows);
3109:
3110:                for (int r = 0; r < this .nbOfRows; r++) {
3111:                    if (!TypeTag.ROW.equals(new TypeTag(input)))
3112:                        throw new ProtocolException("A row was expected");
3113:
3114:                    // First let's flag null values using a burst of booleans
3115:                    // TODO: we should compress this
3116:                    for (int col = 0; col < nbOfColumns; col++)
3117:                        nulls[col] = input.readBoolean();
3118:
3119:                    Object[] row = new Object[this .nbOfColumns];
3120:
3121:                    /**
3122:                     * Here we are sure that serializers are initialized because:
3123:                     * <p>
3124:                     * (1) we went through {@link #DriverResultSet(Connection)} at least once
3125:                     * before
3126:                     * <p>
3127:                     * (2) and there was a non-zero ResultSet transfered, else we would not
3128:                     * come here again.
3129:                     */
3130:                    for (int col = 0; col < this .nbOfColumns; col++)
3131:                        if (nulls[col])
3132:                            row[col] = null;
3133:                        else
3134:                            row[col] = serializers[col]
3135:                                    .receiveFromStream(input);
3136:
3137:                    this .data.add(row);
3138:                }
3139:
3140:                this .hasMoreData = input.readBoolean();
3141:            }
3142:
3143:            /**
3144:             * Set the statement.
3145:             * 
3146:             * @param stmt The statement to set
3147:             * @throws SQLException if an error occurs
3148:             */
3149:            protected void setStatement(Statement stmt) throws SQLException {
3150:                owningStatement = stmt;
3151:                fetchSize = stmt.getFetchSize();
3152:                resultSetConcurrency = stmt.getResultSetConcurrency();
3153:                resultSetType = stmt.getResultSetType();
3154:            }
3155:
3156:            /**
3157:             * Builds a hash between column names and their indices for fast retrieval. An
3158:             * earlier name or label currently preempts any later name or label. This
3159:             * looks compliant with the 3.0 spec and 4.0 draft.
3160:             */
3161:            private void buildIndexMapping(Hashtable table, boolean sensitive) {
3162:                int numFields = nbOfColumns;
3163:
3164:                for (int i = 0; i < numFields; i++) {
3165:                    // pgjdbc and MySQL connector/J < 5 make no difference between name and
3166:                    // label. See SEQUOIA-746 and SEQUOIA-218
3167:                    putFieldNameInIndexMapping(fields[i].getFieldLabel(), i,
3168:                            sensitive, table);
3169:                    putFieldNameInIndexMapping(fields[i].getFieldName(), i,
3170:                            sensitive, table);
3171:
3172:                    /*
3173:                     * Add the fully qualified name in any case. It is fully qualified and
3174:                     * guaranteed, therefore, not to be a duplicate unless it really is the
3175:                     * same column in the same table ...
3176:                     */
3177:                    putFieldNameInIndexMapping(fields[i].getFullName(), i,
3178:                            sensitive, table);
3179:                }
3180:            }
3181:
3182:            private void putFieldNameInIndexMapping(String name, int i,
3183:                    boolean sensitive, Hashtable table) {
3184:                if ((name == null) || "".equals(name))
3185:                    return;
3186:
3187:                Integer index = new Integer(i);
3188:
3189:                String key = sensitive ? name : name.toLowerCase();
3190:
3191:                if (!table.containsKey(key))
3192:                    table.put(key, index);
3193:            }
3194:
3195:            /**
3196:             * Builds a delete statement for deleting rows with Updatable ResultSets
3197:             * 
3198:             * @throws SQLException
3199:             */
3200:            private void buildDeleteStatement() throws SQLException {
3201:                // Check that ResultSet can be updated
3202:                this .checkUpdatability();
3203:
3204:                // Build delete statement for this ResultSet
3205:                StringBuffer sb = new StringBuffer();
3206:                sb.append("DELETE FROM ");
3207:                sb.append(fields[0].getTableName());
3208:                sb.append(" WHERE ");
3209:                for (int i = 0; i < primaryKeyColumns.length; ++i) {
3210:                    if (i > 0)
3211:                        sb.append(" AND ");
3212:                    sb.append(primaryKeyColumns[i]);
3213:                    sb.append(" = ?");
3214:                }
3215:
3216:                // set delete statement
3217:                deleteStatement = this .connection.prepareStatement(sb
3218:                        .toString());
3219:            }
3220:
3221:            /**
3222:             * Builds a insert statement for inserting rows with Updatable ResultSets
3223:             * 
3224:             * @throws SQLException
3225:             */
3226:            private void buildInsertStatement() throws SQLException {
3227:                // Check that ResultSet can be updated
3228:                this .checkUpdatability();
3229:
3230:                // Build insert statement for this ResultSet
3231:                StringBuffer sb = new StringBuffer();
3232:                sb.append("INSERT INTO ");
3233:                sb.append(fields[0].getTableName());
3234:                sb.append(" (");
3235:                for (int i = 0; i < fields.length; ++i) {
3236:                    if (i > 0)
3237:                        sb.append(", ");
3238:                    sb.append(fields[i].getFieldName());
3239:                }
3240:                sb.append(") VALUES (");
3241:                for (int i = 0; i < fields.length; ++i) {
3242:                    if (i > 0)
3243:                        sb.append(", ");
3244:                    sb.append("?");
3245:                }
3246:                sb.append(")");
3247:
3248:                // set insert statement
3249:                insertStatement = this .connection.prepareStatement(sb
3250:                        .toString());
3251:            }
3252:
3253:            /**
3254:             * Builds a select statement for refreshing rows in Updatable ResultSets
3255:             * 
3256:             * @throws SQLException
3257:             */
3258:            private void buildRefreshStatement() throws SQLException {
3259:                // Check that ResultSet can be updated
3260:                this .checkUpdatability();
3261:
3262:                // Build refresh statement for this ResultSet
3263:                StringBuffer sb = new StringBuffer();
3264:                sb.append("SELECT ");
3265:                for (int i = 0; i < fields.length; ++i) {
3266:                    if (i > 0)
3267:                        sb.append(", ");
3268:                    sb.append(fields[i].getFieldName());
3269:                }
3270:                sb.append(" FROM ");
3271:                sb.append(fields[0].getTableName());
3272:                sb.append(" WHERE ");
3273:                for (int i = 0; i < primaryKeyColumns.length; ++i) {
3274:                    if (i > 0)
3275:                        sb.append(" AND ");
3276:                    sb.append(primaryKeyColumns[i]);
3277:                    sb.append(" = ?");
3278:                }
3279:
3280:                // set refresh statement
3281:                refreshStatement = this .connection.prepareStatement(sb
3282:                        .toString());
3283:            }
3284:
3285:            /**
3286:             * Builds an update statement for updating rows with Updatable ResultSets
3287:             * 
3288:             * @throws SQLException
3289:             */
3290:            private void buildUpdateStatement() throws SQLException {
3291:                // Check that ResultSet can be updated
3292:                this .checkUpdatability();
3293:
3294:                // Build update statement for this ResultSet
3295:                StringBuffer sb = new StringBuffer();
3296:                sb.append("UPDATE ");
3297:                sb.append(fields[0].getTableName());
3298:                sb.append(" SET ");
3299:                for (int i = 0; i < fields.length; ++i) {
3300:                    if (i > 0)
3301:                        sb.append(", ");
3302:                    sb.append(fields[i].getFieldName());
3303:                    sb.append(" = ?");
3304:                }
3305:                sb.append(" WHERE ");
3306:                for (int i = 0; i < primaryKeyColumns.length; ++i) {
3307:                    if (i > 0)
3308:                        sb.append(" AND ");
3309:                    sb.append(primaryKeyColumns[i]);
3310:                    sb.append(" = ?");
3311:                }
3312:
3313:                // set update statement
3314:                updateStatement = this .connection.prepareStatement(sb
3315:                        .toString());
3316:            }
3317:
3318:            /**
3319:             * Retrieves the primary key for the table referenced by this ResultSet
3320:             * 
3321:             * @throws SQLException
3322:             */
3323:            private void extractPrimaryKey() throws SQLException {
3324:                // sanity check
3325:                if (fields[0].getTableName() == null
3326:                        || fields[0].getTableName().length() == 0)
3327:                    throw new SQLException(
3328:                            "Could not extractPrimaryKeys: empty tablename");
3329:
3330:                ResultSet res = this .connection.getPrimaryKeys(null, null,
3331:                        fields[0].getTableName());
3332:
3333:                try {
3334:                    primaryKeyColumns = new String[((DriverResultSet) res).nbOfRows];
3335:                    while (res.next())
3336:                        primaryKeyColumns[res.getRow() - 1] = res.getString(4);
3337:                } finally {
3338:                    // Clean up
3339:                    res.close();
3340:                }
3341:            }
3342:
3343:            /**
3344:             * Basic checks for Updatable ResultSets
3345:             * 
3346:             * @throws SQLException
3347:             */
3348:            private void checkUpdatability() throws SQLException {
3349:                // Check ResultSet Concurrency type
3350:                switch (resultSetConcurrency) {
3351:                case ResultSet.CONCUR_READ_ONLY:
3352:                    throw new SQLException("Cannot update ResultSet with "
3353:                            + "concurrency mode CONCUR_READ_ONLY");
3354:                case ResultSet.CONCUR_UPDATABLE:
3355:                    break;
3356:                default:
3357:                    throw new SQLException(
3358:                            "Invalid ResultSet concurrency mode: "
3359:                                    + resultSetConcurrency);
3360:                }
3361:
3362:                // Check that the query selects only one table
3363:                String tableName = fields[0].getTableName();
3364:                for (int i = 1; i < nbOfColumns; ++i)
3365:                    if (!tableName.equals(fields[i].getTableName()))
3366:                        throw new SQLException(UPDATEABLE_MESSAGE);
3367:
3368:                // Check if need to get primary keys
3369:                if (primaryKeyColumns == null)
3370:                    this .extractPrimaryKey();
3371:
3372:                // Check that the query selects the full primary key
3373:                for (int i = 0; i < primaryKeyColumns.length; ++i)
3374:                    try {
3375:                        findColumn(primaryKeyColumns[i]);
3376:                    } catch (SQLException e) {
3377:                        throw new SQLException(UPDATEABLE_MESSAGE);
3378:                    }
3379:            }
3380:
3381:            /**
3382:             * Sanity checks for result parsing
3383:             * 
3384:             * @param columnIndex the column to check
3385:             * @throws SQLException if an error occurs
3386:             */
3387:            private void checkRowAndColPosAndSetNullFlag(int columnIndex)
3388:                    throws SQLException {
3389:                checkIfClosed();
3390:
3391:                closeCurrentStreamIfExists();
3392:
3393:                if (!inserting)
3394:                    checkRowPos();
3395:
3396:                if (fields == null)
3397:                    throw new java.sql.SQLException(
3398:                            "Query generated no fields for ResultSet");
3399:
3400:                if (columnIndex < 1 || columnIndex > nbOfColumns)
3401:                    throw new java.sql.SQLException(
3402:                            "Column Index out of range ( " + columnIndex
3403:                                    + " > " + nbOfColumns + ").");
3404:
3405:                try {
3406:                    Object obj;
3407:                    if (inserting || updating)
3408:                        obj = tempRow[columnIndex - 1];
3409:                    else
3410:                        obj = ((Object[]) data.get(currentRow))[columnIndex - 1];
3411:
3412:                    if (obj == null)
3413:                        wasNullFlag = true;
3414:                    else
3415:                        wasNullFlag = false;
3416:                } catch (NullPointerException e) {
3417:                    wasNullFlag = true;
3418:                }
3419:            }
3420:
3421:            /**
3422:             * Checks that the cursor is on row in the ResultSet
3423:             * 
3424:             * @throws SQLException
3425:             */
3426:            private void checkRowPos() throws SQLException {
3427:                if (currentRow < 0)
3428:                    throw new SQLException("Before start of result set");
3429:
3430:                if (currentRow == nbOfRows)
3431:                    throw new SQLException("After end of result set");
3432:            }
3433:
3434:            /**
3435:             * Checks that the update flag is set when updating a row. The first time an
3436:             * update is done on a row this method will prepare the ResultSet for update
3437:             * 
3438:             * @throws SQLException
3439:             */
3440:            private void checkUpdateFlagAndPrepareUpdateIfNeeded()
3441:                    throws SQLException {
3442:                if (updating)
3443:                    return;
3444:
3445:                this .checkRowPos();
3446:
3447:                if (updateStatement == null)
3448:                    this .buildUpdateStatement();
3449:
3450:                tempRow = (Object[]) ((Object[]) data.get(currentRow)).clone();
3451:
3452:                for (int i = 0; i < nbOfColumns; ++i)
3453:                    updateStatement.setObject(i + 1, tempRow[i]);
3454:
3455:                updating = true;
3456:            }
3457:
3458:            /**
3459:             * Check if the ResultSet if closed and throws a SQLException if so.
3460:             * 
3461:             * @throws SQLException if the ResultSet is closed
3462:             */
3463:            private void checkIfClosed() throws SQLException {
3464:                if (isClosed)
3465:                    throw new SQLException(
3466:                            "Trying to access a closed ResultSet");
3467:            }
3468:
3469:            /**
3470:             * Check if the ResultSet can be scrolled.
3471:             * 
3472:             * @throws SQLException if the ResultSet is closed or if its type is
3473:             *           TYPE_FORWARD_ONLY.
3474:             */
3475:            private void checkIfScrollable() throws SQLException {
3476:                checkIfClosed();
3477:                if (resultSetType == ResultSet.TYPE_FORWARD_ONLY) {
3478:                    throw new SQLException(
3479:                            "Operation requires a scrollable ResultSet, but this ResultSet is FORWARD_ONLY");
3480:                }
3481:            }
3482:
3483:            /**
3484:             * Close a previously created input stream if needed.
3485:             */
3486:            private void closeCurrentStreamIfExists() {
3487:                if (currentStream != null) {
3488:                    try {
3489:                        // since we use only ByteArrayInputStreams for now, this is a no-op.
3490:                        currentStream.close();
3491:                    } catch (IOException ignore) {
3492:                    } finally {
3493:                        currentStream = null;
3494:                    }
3495:                }
3496:            }
3497:
3498:            // -------------------------- JDBC 3.0
3499:            // ----------------------------------------
3500:
3501:            /**
3502:             * Retrieves the value of the designated column in the current row of this
3503:             * <code>ResultSet</code> object as a <code>java.net.URL</code> object in
3504:             * the Java programming language.
3505:             * 
3506:             * @param columnIndex the index of the column 1 is the first, 2 is the
3507:             *          second,...
3508:             * @return the column value as a <code>java.net.URL</code> object; if the
3509:             *         value is SQL <code>NULL</code>, the value returned is
3510:             *         <code>null</code> in the Java programming language
3511:             * @exception SQLException if a database access error occurs, or if a URL is
3512:             *              malformed
3513:             * @since JDK 1.4
3514:             */
3515:            public java.net.URL getURL(int columnIndex) throws SQLException {
3516:                checkRowAndColPosAndSetNullFlag(columnIndex);
3517:
3518:                if (wasNullFlag)
3519:                    return null;
3520:
3521:                if (inserting || updating)
3522:                    return (URL) tempRow[columnIndex - 1];
3523:                else
3524:                    return (URL) (((Object[]) data.get(currentRow))[columnIndex - 1]);
3525:            }
3526:
3527:            /**
3528:             * Retrieves the value of the designated column in the current row of this
3529:             * <code>ResultSet</code> object as a <code>java.net.URL</code> object in
3530:             * the Java programming language.
3531:             * 
3532:             * @param columnName the SQL name of the column
3533:             * @return the column value as a <code>java.net.URL</code> object; if the
3534:             *         value is SQL <code>NULL</code>, the value returned is
3535:             *         <code>null</code> in the Java programming language
3536:             * @exception SQLException if a database access error occurs or if a URL is
3537:             *              malformed
3538:             * @since JDK 1.4
3539:             */
3540:            public java.net.URL getURL(String columnName) throws SQLException {
3541:                return getURL(findColumn(columnName));
3542:            }
3543:
3544:            /**
3545:             * Updates the designated column with a <code>java.sql.Ref</code> value. The
3546:             * updater methods are used to update column values in the current row or the
3547:             * insert row. The updater methods do not update the underlying database;
3548:             * instead the <code>updateRow</code> or <code>insertRow</code> methods
3549:             * are called to update the database.
3550:             * 
3551:             * @param columnIndex the first column is 1, the second is 2, ...
3552:             * @param x the new column value
3553:             * @exception SQLException if a database access error occurs
3554:             * @since JDK 1.4
3555:             */
3556:            public void updateRef(int columnIndex, java.sql.Ref x)
3557:                    throws SQLException {
3558:                throw new NotImplementedException("updateRef");
3559:            }
3560:
3561:            /**
3562:             * Updates the designated column with a <code>java.sql.Ref</code> value. The
3563:             * updater methods are used to update column values in the current row or the
3564:             * insert row. The updater methods do not update the underlying database;
3565:             * instead the <code>updateRow</code> or <code>insertRow</code> methods
3566:             * are called to update the database.
3567:             * 
3568:             * @param columnName the name of the column
3569:             * @param x the new column value
3570:             * @exception SQLException if a database access error occurs
3571:             * @since JDK 1.4
3572:             */
3573:            public void updateRef(String columnName, java.sql.Ref x)
3574:                    throws SQLException {
3575:                updateRef(findColumn(columnName), x);
3576:            }
3577:
3578:            /**
3579:             * Updates the designated column with a <code>java.sql.Blob</code> value.
3580:             * The updater methods are used to update column values in the current row or
3581:             * the insert row. The updater methods do not update the underlying database;
3582:             * instead the <code>updateRow</code> or <code>insertRow</code> methods
3583:             * are called to update the database.
3584:             * 
3585:             * @param columnIndex the first column is 1, the second is 2, ...
3586:             * @param x the new column value
3587:             * @exception SQLException if a database access error occurs
3588:             * @since JDK 1.4
3589:             */
3590:            public void updateBlob(int columnIndex, java.sql.Blob x)
3591:                    throws SQLException {
3592:                throw new NotImplementedException("updateBlob");
3593:            }
3594:
3595:            /**
3596:             * Updates the designated column with a <code>java.sql.Blob</code> value.
3597:             * The updater methods are used to update column values in the current row or
3598:             * the insert row. The updater methods do not update the underlying database;
3599:             * instead the <code>updateRow</code> or <code>insertRow</code> methods
3600:             * are called to update the database.
3601:             * 
3602:             * @param columnName the name of the column
3603:             * @param x the new column value
3604:             * @exception SQLException if a database access error occurs
3605:             * @since JDK 1.4
3606:             */
3607:            public void updateBlob(String columnName, java.sql.Blob x)
3608:                    throws SQLException {
3609:                updateBlob(findColumn(columnName), x);
3610:            }
3611:
3612:            /**
3613:             * Updates the designated column with a <code>java.sql.Clob</code> value.
3614:             * The updater methods are used to update column values in the current row or
3615:             * the insert row. The updater methods do not update the underlying database;
3616:             * instead the <code>updateRow</code> or <code>insertRow</code> methods
3617:             * are called to update the database.
3618:             * 
3619:             * @param columnIndex the first column is 1, the second is 2, ...
3620:             * @param x the new column value
3621:             * @exception SQLException if a database access error occurs
3622:             * @since JDK 1.4
3623:             */
3624:            public void updateClob(int columnIndex, java.sql.Clob x)
3625:                    throws SQLException {
3626:                throw new NotImplementedException("updateClob");
3627:            }
3628:
3629:            /**
3630:             * Updates the designated column with a <code>java.sql.Clob</code> value.
3631:             * The updater methods are used to update column values in the current row or
3632:             * the insert row. The updater methods do not update the underlying database;
3633:             * instead the <code>updateRow</code> or <code>insertRow</code> methods
3634:             * are called to update the database.
3635:             * 
3636:             * @param columnName the name of the column
3637:             * @param x the new column value
3638:             * @exception SQLException if a database access error occurs
3639:             * @since JDK 1.4
3640:             */
3641:            public void updateClob(String columnName, java.sql.Clob x)
3642:                    throws SQLException {
3643:                updateClob(findColumn(columnName), x);
3644:            }
3645:
3646:            /**
3647:             * Updates the designated column with a <code>java.sql.Array</code> value.
3648:             * The updater methods are used to update column values in the current row or
3649:             * the insert row. The updater methods do not update the underlying database;
3650:             * instead the <code>updateRow</code> or <code>insertRow</code> methods
3651:             * are called to update the database.
3652:             * 
3653:             * @param columnIndex the first column is 1, the second is 2, ...
3654:             * @param x the new column value
3655:             * @exception SQLException if a database access error occurs
3656:             * @since JDK 1.4
3657:             */
3658:            public void updateArray(int columnIndex, java.sql.Array x)
3659:                    throws SQLException {
3660:                throw new NotImplementedException("updateArray");
3661:            }
3662:
3663:            /**
3664:             * Updates the designated column with a <code>java.sql.Array</code> value.
3665:             * The updater methods are used to update column values in the current row or
3666:             * the insert row. The updater methods do not update the underlying database;
3667:             * instead the <code>updateRow</code> or <code>insertRow</code> methods
3668:             * are called to update the database.
3669:             * 
3670:             * @param columnName the name of the column
3671:             * @param x the new column value
3672:             * @exception SQLException if a database access error occurs
3673:             * @since JDK 1.4
3674:             */
3675:            public void updateArray(String columnName, java.sql.Array x)
3676:                    throws SQLException {
3677:                updateArray(findColumn(columnName), x);
3678:            }
3679:
3680:            /**
3681:             * Get the value of a column in the current row as a Java byte.
3682:             * 
3683:             * @param columnIndex the first column is 1, the second is 2,...
3684:             * @return the column value; 0 if SQL NULL
3685:             * @exception SQLException if a database access error occurs
3686:             */
3687:            public byte getByte(int columnIndex) throws SQLException {
3688:                checkRowAndColPosAndSetNullFlag(columnIndex);
3689:
3690:                if (wasNullFlag)
3691:                    return 0;
3692:
3693:                Object obj;
3694:                if (inserting || updating)
3695:                    obj = tempRow[columnIndex - 1];
3696:                else
3697:                    obj = ((Object[]) data.get(currentRow))[columnIndex - 1];
3698:
3699:                if (obj instanceof  Number) {
3700:                    return ((Number) obj).byteValue();
3701:                }
3702:
3703:                // the object is not of type number we parse the string representation
3704:                try {
3705:                    String string = obj.toString();
3706:                    string = string.trim();
3707:                    return Byte.parseByte(string);
3708:                } catch (NumberFormatException e) {
3709:                    throw new SQLException("the value " + obj.toString()
3710:                            + " is not a valid byte");
3711:                }
3712:            }
3713:
3714:            /**
3715:             * @see java.lang.Object#toString()
3716:             */
3717:            public String toString() {
3718:                return nbOfRows + " rows - " + nbOfColumns
3719:                        + " columns - current row:" + currentRow
3720:                        + " - hasMoreData:" + hasMoreData + " - isClosed:"
3721:                        + isClosed;
3722:            }
3723:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.