History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/com/sun/rowset/CachedRowSetImpl.java (1 of 18352 files). Show all

Unified · Split

java/pkg/com/sun/rowset/CachedRowSetImpl.java+10133−0
@@ -0,0 +1,10133 @@
1/*
2 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.rowset;
27
28import java.sql.*;
29import javax.sql.*;
30import java.io.*;
31import java.math.*;
32import java.util.*;
33import java.text.*;
34
35import javax.sql.rowset.*;
36import javax.sql.rowset.spi.*;
37import javax.sql.rowset.serial.*;
38import com.sun.rowset.internal.*;
39import com.sun.rowset.providers.*;
40
41/**
42 * The standard implementation of the <code>CachedRowSet</code> interface.
43 *
44 * See interface defintion for full behaviour and implementation requirements.
45 * This reference implementation has made provision for a one-to-one write back
46 * facility and it is curremtly be possible to change the peristence provider
47 * during the life-time of any CachedRowSetImpl.
48 *
49 * @author Jonathan Bruce, Amit Handa
50 */
51
52public class CachedRowSetImpl extends BaseRowSet implements RowSet, RowSetInternal, Serializable, Cloneable, CachedRowSet {
53
54 /**
55 * The <code>SyncProvider</code> used by the CachedRowSet
56 */
57 private SyncProvider provider;
58
59 /**
60 * The <code>RowSetReaderImpl</code> object that is the reader
61 * for this rowset. The method <code>execute</code> uses this
62 * reader as part of its implementation.
63 * @serial
64 */
65 private RowSetReader rowSetReader;
66
67 /**
68 * The <code>RowSetWriterImpl</code> object that is the writer
69 * for this rowset. The method <code>acceptChanges</code> uses
70 * this writer as part of its implementation.
71 * @serial
72 */
73 private RowSetWriter rowSetWriter;
74
75 /**
76 * The <code>Connection</code> object that connects with this
77 * <code>CachedRowSetImpl</code> object's current underlying data source.
78 */
79 private transient Connection conn;
80
81 /**
82 * The <code>ResultSetMetaData</code> object that contains information
83 * about the columns in the <code>ResultSet</code> object that is the
84 * current source of data for this <code>CachedRowSetImpl</code> object.
85 */
86 private transient ResultSetMetaData RSMD;
87
88 /**
89 * The <code>RowSetMetaData</code> object that contains information about
90 * the columns in this <code>CachedRowSetImpl</code> object.
91 * @serial
92 */
93 private RowSetMetaDataImpl RowSetMD;
94
95 // Properties of this RowSet
96
97 /**
98 * An array containing the columns in this <code>CachedRowSetImpl</code>
99 * object that form a unique identifier for a row. This array
100 * is used by the writer.
101 * @serial
102 */
103 private int keyCols[];
104
105 /**
106 * The name of the table in the underlying database to which updates
107 * should be written. This name is needed because most drivers
108 * do not return this information in a <code>ResultSetMetaData</code>
109 * object.
110 * @serial
111 */
112 private String tableName;
113
114 /**
115 * A <code>Vector</code> object containing the <code>Row</code>
116 * objects that comprise this <code>CachedRowSetImpl</code> object.
117 * @serial
118 */
119 private Vector<Object> rvh;
120
121 /**
122 * The current postion of the cursor in this <code>CachedRowSetImpl</code>
123 * object.
124 * @serial
125 */
126 private int cursorPos;
127
128 /**
129 * The current postion of the cursor in this <code>CachedRowSetImpl</code>
130 * object not counting rows that have been deleted, if any.
131 * <P>
132 * For example, suppose that the cursor is on the last row of a rowset
133 * that started with five rows and subsequently had the second and third
134 * rows deleted. The <code>absolutePos</code> would be <code>3</code>,
135 * whereas the <code>cursorPos</code> would be <code>5</code>.
136 * @serial
137 */
138 private int absolutePos;
139
140 /**
141 * The number of deleted rows currently in this <code>CachedRowSetImpl</code>
142 * object.
143 * @serial
144 */
145 private int numDeleted;
146
147 /**
148 * The total number of rows currently in this <code>CachedRowSetImpl</code>
149 * object.
150 * @serial
151 */
152 private int numRows;
153
154 /**
155 * A special row used for constructing a new row. A new
156 * row is constructed by using <code>ResultSet.updateXXX</code>
157 * methods to insert column values into the insert row.
158 * @serial
159 */
160 private InsertRow insertRow;
161
162 /**
163 * A <code>boolean</code> indicating whether the cursor is
164 * currently on the insert row.
165 * @serial
166 */
167 private boolean onInsertRow;
168
169 /**
170 * The field that temporarily holds the last position of the
171 * cursor before it moved to the insert row, thus preserving
172 * the number of the current row to which the cursor may return.
173 * @serial
174 */
175 private int currentRow;
176
177 /**
178 * A <code>boolean</code> indicating whether the last value
179 * returned was an SQL <code>NULL</code>.
180 * @serial
181 */
182 private boolean lastValueNull;
183
184 /**
185 * A <code>SQLWarning</code> which logs on the warnings
186 */
187 private SQLWarning sqlwarn;
188
189 /**
190 * Used to track match column for JoinRowSet consumption
191 */
192 private String strMatchColumn ="";
193
194 /**
195 * Used to track match column for JoinRowSet consumption
196 */
197 private int iMatchColumn = -1;
198
199 /**
200 * A <code>RowSetWarning</code> which logs on the warnings
201 */
202 private RowSetWarning rowsetWarning;
203
204 /**
205 * The default SyncProvider for the RI CachedRowSetImpl
206 */
207 private String DEFAULT_SYNC_PROVIDER = "com.sun.rowset.providers.RIOptimisticProvider";
208
209 /**
210 * The boolean variable indicating locatorsUpdateValue
211 */
212 private boolean dbmslocatorsUpdateCopy;
213
214 /**
215 * The <code>ResultSet</code> object that is used to maintain the data when
216 * a ResultSet and start position are passed as parameters to the populate function
217 */
218 private transient ResultSet resultSet;
219
220 /**
221 * The integer value indicating the end position in the ResultSetwhere the picking
222 * up of rows for populating a CachedRowSet object was left off.
223 */
224 private int endPos;
225
226 /**
227 * The integer value indicating the end position in the ResultSetwhere the picking
228 * up of rows for populating a CachedRowSet object was left off.
229 */
230 private int prevEndPos;
231
232 /**
233 * The integer value indicating the position in the ResultSet, to populate the
234 * CachedRowSet object.
235 */
236 private int startPos;
237
238 /**
239 * The integer value indicating the positon from where the page prior to this
240 * was populated.
241 */
242 private int startPrev;
243
244 /**
245 * The integer value indicating size of the page.
246 */
247 private int pageSize;
248
249 /**
250 * The integer value indicating number of rows that have been processed so far.
251 * Used for checking whether maxRows has been reached or not.
252 */
253 private int maxRowsreached;
254 /**
255 * The boolean value when true signifies that pages are still to follow and a
256 * false value indicates that this is the last page.
257 */
258 private boolean pagenotend = true;
259
260 /**
261 * The boolean value indicating whether this is the first page or not.
262 */
263 private boolean onFirstPage;
264
265 /**
266 * The boolean value indicating whether this is the last page or not.
267 */
268 private boolean onLastPage;
269
270 /**
271 * The integer value indicating how many times the populate function has been called.
272 */
273 private int populatecallcount;
274
275 /**
276 * The integer value indicating the total number of rows to be processed in the
277 * ResultSet object passed to the populate function.
278 */
279 private int totalRows;
280
281 /**
282 * The boolean value indicating how the CahedRowSet object has been populated for
283 * paging purpose. True indicates that connection parameter is passed.
284 */
285 private boolean callWithCon;
286
287 /**
288 * CachedRowSet reader object to read the data from the ResultSet when a connection
289 * parameter is passed to populate the CachedRowSet object for paging.
290 */
291 private CachedRowSetReader crsReader;
292
293 /**
294 * The Vector holding the Match Columns
295 */
296 private Vector<Integer> iMatchColumns;
297
298 /**
299 * The Vector that will hold the Match Column names.
300 */
301 private Vector<String> strMatchColumns;
302
303 /**
304 * Trigger that indicates whether the active SyncProvider is exposes the
305 * additional TransactionalWriter method
306 */
307 private boolean tXWriter = false;
308
309 /**
310 * The field object for a transactional RowSet writer
311 */
312 private TransactionalWriter tWriter = null;
313
314 protected transient JdbcRowSetResourceBundle resBundle;
315
316 private boolean updateOnInsert;
317
318
319
320 /**
321 * Constructs a new default <code>CachedRowSetImpl</code> object with
322 * the capacity to hold 100 rows. This new object has no metadata
323 * and has the following default values:
324 * <pre>
325 * onInsertRow = false
326 * insertRow = null
327 * cursorPos = 0
328 * numRows = 0
329 * showDeleted = false
330 * queryTimeout = 0
331 * maxRows = 0
332 * maxFieldSize = 0
333 * rowSetType = ResultSet.TYPE_SCROLL_INSENSITIVE
334 * concurrency = ResultSet.CONCUR_UPDATABLE
335 * readOnly = false
336 * isolation = Connection.TRANSACTION_READ_COMMITTED
337 * escapeProcessing = true
338 * onInsertRow = false
339 * insertRow = null
340 * cursorPos = 0
341 * absolutePos = 0
342 * numRows = 0
343 * </pre>
344 * A <code>CachedRowSetImpl</code> object is configured to use the default
345 * <code>RIOptimisticProvider</code> implementation to provide connectivity
346 * and synchronization capabilities to the set data source.
347 * <P>
348 * @throws SQLException if an error occurs
349 */
350 public CachedRowSetImpl() throws SQLException {
351
352 try {
353 resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
354 } catch(IOException ioe) {
355 throw new RuntimeException(ioe);
356 }
357
358 // set the Reader, this maybe overridden latter
359 provider =
360 (SyncProvider)SyncFactory.getInstance(DEFAULT_SYNC_PROVIDER);
361
362 if (!(provider instanceof RIOptimisticProvider)) {
363 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidp").toString());
364 }
365
366 rowSetReader = (CachedRowSetReader)provider.getRowSetReader();
367 rowSetWriter = (CachedRowSetWriter)provider.getRowSetWriter();
368
369 // allocate the parameters collection
370 initParams();
371
372 initContainer();
373
374 // set up some default values
375 initProperties();
376
377 // insert row setup
378 onInsertRow = false;
379 insertRow = null;
380
381 // set the warninings
382 sqlwarn = new SQLWarning();
383 rowsetWarning = new RowSetWarning();
384
385 }
386
387 /**
388 * Provides a <code>CachedRowSetImpl</code> instance with the same default properties as
389 * as the zero parameter constructor.
390 * <pre>
391 * onInsertRow = false
392 * insertRow = null
393 * cursorPos = 0
394 * numRows = 0
395 * showDeleted = false
396 * queryTimeout = 0
397 * maxRows = 0
398 * maxFieldSize = 0
399 * rowSetType = ResultSet.TYPE_SCROLL_INSENSITIVE
400 * concurrency = ResultSet.CONCUR_UPDATABLE
401 * readOnly = false
402 * isolation = Connection.TRANSACTION_READ_COMMITTED
403 * escapeProcessing = true
404 * onInsertRow = false
405 * insertRow = null
406 * cursorPos = 0
407 * absolutePos = 0
408 * numRows = 0
409 * </pre>
410 *
411 * However, applications will have the means to specify at runtime the
412 * desired <code>SyncProvider</code> object.
413 * <p>
414 * For example, creating a <code>CachedRowSetImpl</code> object as follows ensures
415 * that a it is established with the <code>com.foo.provider.Impl</code> synchronization
416 * implementation providing the synchronization mechanism for this disconnected
417 * <code>RowSet</code> object.
418 * <pre>
419 * Hashtable env = new Hashtable();
420 * env.put(javax.sql.rowset.spi.SyncFactory.ROWSET_PROVIDER_NAME,
421 * "com.foo.provider.Impl");
422 * CachedRowSetImpl crs = new CachedRowSet(env);
423 * </pre>
424 * <p>
425 * Calling this constructor with a <code>null</code> parameter will
426 * cause the <code>SyncFactory</code> to provide the reference
427 * optimistic provider <code>com.sun.rowset.providers.RIOptimisticProvider</code>.
428 * <p>
429 * In addition, the following properties can be associated with the
430 * provider to assist in determining the choice of the synchronizaton
431 * provider such as:
432 * <ul>
433 * <li><code>ROWSET_SYNC_PROVIDER</code> - the property specifying the the
434 * <code>SyncProvider</code> class name to be instantiated by the
435 * <code>SyncFacttory</code>
436 * <li><code>ROWSET_SYNC_VENDOR</code> - the property specifying the software
437 * vendor associated with a <code>SyncProvider</code> implementation.
438 * <li><code>ROWSET_SYNC_PROVIDER_VER</code> - the property specifying the
439 * version of the <code>SyncProvider</code> implementation provided by the
440 * software vendor.
441 * </ul>
442 * More specific detailes are available in the <code>SyncFactory</code>
443 * and <code>SyncProvider</code> specificiations later in this document.
444 * <p>
445 * @param env a <code>Hashtable</code> object with a list of desired
446 * synchronization providers
447 * @throws SQLException if the requested provider cannot be found by the
448 * synchonization factory
449 * @see SyncProvider
450 */
451
452 public CachedRowSetImpl(Hashtable env) throws SQLException {
453
454
455 try {
456 resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
457 } catch(IOException ioe) {
458 throw new RuntimeException(ioe);
459 }
460
461 if (env == null) {
462 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.nullhash").toString());
463 }
464
465 String providerName = (String)env.get(
466 javax.sql.rowset.spi.SyncFactory.ROWSET_SYNC_PROVIDER);
467
468 // set the Reader, this maybe overridden latter
469 provider =
470 (SyncProvider)SyncFactory.getInstance(providerName);
471
472 rowSetReader = provider.getRowSetReader();
473 rowSetWriter = provider.getRowSetWriter();
474
475 initParams(); // allocate the parameters collection
476 initContainer();
477 initProperties(); // set up some default values
478 }
479
480 /**
481 * Sets the <code>rvh</code> field to a new <code>Vector</code>
482 * object with a capacity of 100 and sets the
483 * <code>cursorPos</code> and <code>numRows</code> fields to zero.
484 */
485 private void initContainer() {
486
487 rvh = new Vector<Object>(100);
488 cursorPos = 0;
489 absolutePos = 0;
490 numRows = 0;
491 numDeleted = 0;
492 }
493
494 /**
495 * Sets the properties for this <code>CachedRowSetImpl</code> object to
496 * their default values. This method is called internally by the
497 * default constructor.
498 */
499
500 private void initProperties() throws SQLException {
501
502 if(resBundle == null) {
503 try {
504 resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
505 } catch(IOException ioe) {
506 throw new RuntimeException(ioe);
507 }
508 }
509 setShowDeleted(false);
510 setQueryTimeout(0);
511 setMaxRows(0);
512 setMaxFieldSize(0);
513 setType(ResultSet.TYPE_SCROLL_INSENSITIVE);
514 setConcurrency(ResultSet.CONCUR_UPDATABLE);
515 if((rvh.size() > 0) && (isReadOnly() == false))
516 setReadOnly(false);
517 else
518 setReadOnly(true);
519 setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
520 setEscapeProcessing(true);
521 //setTypeMap(null);
522 checkTransactionalWriter();
523
524 //Instantiating the vector for MatchColumns
525
526 iMatchColumns = new Vector<Integer>(10);
527 for(int i = 0; i < 10 ; i++) {
528 iMatchColumns.add(i,Integer.valueOf(-1));
529 }
530
531 strMatchColumns = new Vector<String>(10);
532 for(int j = 0; j < 10; j++) {
533 strMatchColumns.add(j,null);
534 }
535 }
536
537 /**
538 * Determine whether the SyncProvider's writer implements the
539 * <code>TransactionalWriter<code> interface
540 */
541 private void checkTransactionalWriter() {
542 if (rowSetWriter != null) {
543 Class c = rowSetWriter.getClass();
544 if (c != null) {
545 Class[] theInterfaces = c.getInterfaces();
546 for (int i = 0; i < theInterfaces.length; i++) {
547 if ((theInterfaces[i].getName()).indexOf("TransactionalWriter") > 0) {
548 tXWriter = true;
549 establishTransactionalWriter();
550 }
551 }
552 }
553 }
554 }
555
556 /**
557 * Sets an private field to all transaction bounddaries to be set
558 */
559 private void establishTransactionalWriter() {
560 tWriter = (TransactionalWriter)provider.getRowSetWriter();
561 }
562
563 //-----------------------------------------------------------------------
564 // Properties
565 //-----------------------------------------------------------------------
566
567 /**
568 * Sets this <code>CachedRowSetImpl</code> object's command property
569 * to the given <code>String</code> object and clears the parameters,
570 * if any, that were set for the previous command.
571 * <P>
572 * The command property may not be needed
573 * if the rowset is produced by a data source, such as a spreadsheet,
574 * that does not support commands. Thus, this property is optional
575 * and may be <code>null</code>.
576 *
577 * @param cmd a <code>String</code> object containing an SQL query
578 * that will be set as the command; may be <code>null</code>
579 * @throws SQLException if an error occurs
580 */
581 public void setCommand(String cmd) throws SQLException {
582
583 super.setCommand(cmd);
584
585 if(!buildTableName(cmd).equals("")) {
586 this.setTableName(buildTableName(cmd));
587 }
588 }
589
590
591 //---------------------------------------------------------------------
592 // Reading and writing data
593 //---------------------------------------------------------------------
594
595 /**
596 * Populates this <code>CachedRowSetImpl</code> object with data from
597 * the given <code>ResultSet</code> object. This
598 * method is an alternative to the method <code>execute</code>
599 * for filling the rowset with data. The method <code>populate</code>
600 * does not require that the properties needed by the method
601 * <code>execute</code>, such as the <code>command</code> property,
602 * be set. This is true because the method <code>populate</code>
603 * is given the <code>ResultSet</code> object from
604 * which to get data and thus does not need to use the properties
605 * required for setting up a connection and executing this
606 * <code>CachedRowSetImpl</code> object's command.
607 * <P>
608 * After populating this rowset with data, the method
609 * <code>populate</code> sets the rowset's metadata and
610 * then sends a <code>RowSetChangedEvent</code> object
611 * to all registered listeners prior to returning.
612 *
613 * @param data the <code>ResultSet</code> object containing the data
614 * to be read into this <code>CachedRowSetImpl</code> object
615 * @throws SQLException if an error occurs; or the max row setting is
616 * violated while populating the RowSet
617 * @see #execute
618 */
619
620 public void populate(ResultSet data) throws SQLException {
621 int rowsFetched;
622 Row currentRow;
623 int numCols;
624 int i;
625 Map<String, Class<?>> map = getTypeMap();
626 Object obj;
627 int mRows;
628
629 if (data == null) {
630 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.populate").toString());
631 }
632 this.resultSet = data;
633
634 // get the meta data for this ResultSet
635 RSMD = data.getMetaData();
636
637 // set up the metadata
638 RowSetMD = new RowSetMetaDataImpl();
639 initMetaData(RowSetMD, RSMD);
640
641 // release the meta-data so that aren't tempted to use it.
642 RSMD = null;
643 numCols = RowSetMD.getColumnCount();
644 mRows = this.getMaxRows();
645 rowsFetched = 0;
646 currentRow = null;
647
648 while ( data.next()) {
649
650 currentRow = new Row(numCols);
651
652 if ( rowsFetched > mRows && mRows > 0) {
653 rowsetWarning.setNextWarning(new RowSetWarning("Populating rows "
654 + "setting has exceeded max row setting"));
655 }
656 for ( i = 1; i <= numCols; i++) {
657 /*
658 * check if the user has set a map. If no map
659 * is set then use plain getObject. This lets
660 * us work with drivers that do not support
661 * getObject with a map in fairly sensible way
662 */
663 if (map == null) {
664 obj = data.getObject(i);
665 } else {
666 obj = data.getObject(i, map);
667 }
668 /*
669 * the following block checks for the various
670 * types that we have to serialize in order to
671 * store - right now only structs have been tested
672 */
673 if (obj instanceof Struct) {
674 obj = new SerialStruct((Struct)obj, map);
675 } else if (obj instanceof SQLData) {
676 obj = new SerialStruct((SQLData)obj, map);
677 } else if (obj instanceof Blob) {
678 obj = new SerialBlob((Blob)obj);
679 } else if (obj instanceof Clob) {
680 obj = new SerialClob((Clob)obj);
681 } else if (obj instanceof java.sql.Array) {
682 if(map != null)
683 obj = new SerialArray((java.sql.Array)obj, map);
684 else
685 obj = new SerialArray((java.sql.Array)obj);
686 }
687
688 ((Row)currentRow).initColumnObject(i, obj);
689 }
690 rowsFetched++;
691 rvh.add(currentRow);
692 }
693
694 numRows = rowsFetched ;
695 // Also rowsFetched should be equal to rvh.size()
696
697 // notify any listeners that the rowset has changed
698 notifyRowSetChanged();
699
700
701 }
702
703 /**
704 * Initializes the given <code>RowSetMetaData</code> object with the values
705 * in the given <code>ResultSetMetaData</code> object.
706 *
707 * @param md the <code>RowSetMetaData</code> object for this
708 * <code>CachedRowSetImpl</code> object, which will be set with
709 * values from rsmd
710 * @param rsmd the <code>ResultSetMetaData</code> object from which new
711 * values for md will be read
712 * @throws SQLException if an error occurs
713 */
714 private void initMetaData(RowSetMetaDataImpl md, ResultSetMetaData rsmd) throws SQLException {
715 int numCols = rsmd.getColumnCount();
716
717 md.setColumnCount(numCols);
718 for (int col=1; col <= numCols; col++) {
719 md.setAutoIncrement(col, rsmd.isAutoIncrement(col));
720 if(rsmd.isAutoIncrement(col))
721 updateOnInsert = true;
722 md.setCaseSensitive(col, rsmd.isCaseSensitive(col));
723 md.setCurrency(col, rsmd.isCurrency(col));
724 md.setNullable(col, rsmd.isNullable(col));
725 md.setSigned(col, rsmd.isSigned(col));
726 md.setSearchable(col, rsmd.isSearchable(col));
727 /*
728 * The PostgreSQL drivers sometimes return negative columnDisplaySize,
729 * which causes an exception to be thrown. Check for it.
730 */
731 int size = rsmd.getColumnDisplaySize(col);
732 if (size < 0) {
733 size = 0;
734 }
735 md.setColumnDisplaySize(col, size);
736 md.setColumnLabel(col, rsmd.getColumnLabel(col));
737 md.setColumnName(col, rsmd.getColumnName(col));
738 md.setSchemaName(col, rsmd.getSchemaName(col));
739 /*
740 * Drivers return some strange values for precision, for non-numeric data, including reports of
741 * non-integer values; maybe we should check type, & set to 0 for non-numeric types.
742 */
743 int precision = rsmd.getPrecision(col);
744 if (precision < 0) {
745 precision = 0;
746 }
747 md.setPrecision(col, precision);
748
749 /*
750 * It seems, from a bug report, that a driver can sometimes return a negative
751 * value for scale. javax.sql.rowset.RowSetMetaDataImpl will throw an exception
752 * if we attempt to set a negative value. As such, we'll check for this case.
753 */
754 int scale = rsmd.getScale(col);
755 if (scale < 0) {
756 scale = 0;
757 }
758 md.setScale(col, scale);
759 md.setTableName(col, rsmd.getTableName(col));
760 md.setCatalogName(col, rsmd.getCatalogName(col));
761 md.setColumnType(col, rsmd.getColumnType(col));
762 md.setColumnTypeName(col, rsmd.getColumnTypeName(col));
763 }
764
765 if( conn != null){
766 // JDBC 4.0 mandates as does the Java EE spec that all DataBaseMetaData methods
767 // must be implemented, therefore, the previous fix for 5055528 is being backed out
768 dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy();
769 }
770 }
771
772 /**
773 * Populates this <code>CachedRowSetImpl</code> object with data,
774 * using the given connection to produce the result set from
775 * which data will be read. A second form of this method,
776 * which takes no arguments, uses the values from this rowset's
777 * user, password, and either url or data source properties to
778 * create a new database connection. The form of <code>execute</code>
779 * that is given a connection ignores these properties.
780 *
781 * @param conn A standard JDBC <code>Connection</code> object that this
782 * <code>CachedRowSet</code> object can pass to a synchronization provider
783 * to establish a connection to the data source
784 * @throws SQLException if an invalid <code>Connection</code> is supplied
785 * or an error occurs in establishing the connection to the
786 * data source
787 * @see #populate
788 * @see java.sql.Connection
789 */
790 public void execute(Connection conn) throws SQLException {
791 // store the connection so the reader can find it.
792 setConnection(conn);
793
794 if(getPageSize() != 0){
795 crsReader = (CachedRowSetReader)provider.getRowSetReader();
796 crsReader.setStartPosition(1);
797 callWithCon = true;
798 crsReader.readData((RowSetInternal)this);
799 }
800
801 // Now call the current reader's readData method
802 else {
803 rowSetReader.readData((RowSetInternal)this);
804 }
805 RowSetMD = (RowSetMetaDataImpl)this.getMetaData();
806
807 if(conn != null){
808 // JDBC 4.0 mandates as does the Java EE spec that all DataBaseMetaData methods
809 // must be implemented, therefore, the previous fix for 5055528 is being backed out
810 dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy();
811 }
812
813 }
814
815 /**
816 * Sets this <code>CachedRowSetImpl</code> object's connection property
817 * to the given <code>Connection</code> object. This method is called
818 * internally by the version of the method <code>execute</code> that takes a
819 * <code>Connection</code> object as an argument. The reader for this
820 * <code>CachedRowSetImpl</code> object can retrieve the connection stored
821 * in the rowset's connection property by calling its
822 * <code>getConnection</code> method.
823 *
824 * @param connection the <code>Connection</code> object that was passed in
825 * to the method <code>execute</code> and is to be stored
826 * in this <code>CachedRowSetImpl</code> object's connection
827 * property
828 */
829 private void setConnection (Connection connection) {
830 conn = connection;
831 }
832
833
834 /**
835 * Propagates all row update, insert, and delete changes to the
836 * underlying data source backing this <code>CachedRowSetImpl</code>
837 * object.
838 * <P>
839 * <b>Note</b>In the reference implementation an optimistic concurrency implementation
840 * is provided as a sample implementation of a the <code>SyncProvider</code>
841 * abstract class.
842 * <P>
843 * This method fails if any of the updates cannot be propagated back
844 * to the data source. When it fails, the caller can assume that
845 * none of the updates are reflected in the data source.
846 * When an exception is thrown, the current row
847 * is set to the first "updated" row that resulted in an exception
848 * unless the row that caused the exception is a "deleted" row.
849 * In that case, when deleted rows are not shown, which is usually true,
850 * the current row is not affected.
851 * <P>
852 * If no <code>SyncProvider</code> is configured, the reference implementation
853 * leverages the <code>RIOptimisticProvider</code> available which provides the
854 * default and reference synchronization capabilities for disconnected
855 * <code>RowSets</code>.
856 *
857 * @throws SQLException if the cursor is on the insert row or the underlying
858 * reference synchronization provider fails to commit the updates
859 * to the datasource
860 * @throws SyncProviderException if an internal error occurs within the
861 * <code>SyncProvider</code> instance during either during the
862 * process or at any time when the <code>SyncProvider</code>
863 * instance touches the data source.
864 * @see #acceptChanges(java.sql.Connection)
865 * @see javax.sql.RowSetWriter
866 * @see javax.sql.rowset.spi.SyncProvider
867 */
868 public void acceptChanges() throws SyncProviderException {
869 if (onInsertRow == true) {
870 throw new SyncProviderException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
871 }
872
873 int saveCursorPos = cursorPos;
874 boolean success = false;
875 boolean conflict = false;
876
877 try {
878 if (rowSetWriter != null) {
879 saveCursorPos = cursorPos;
880 conflict = rowSetWriter.writeData((RowSetInternal)this);
881 cursorPos = saveCursorPos;
882 }
883
884 if ((tXWriter) && this.COMMIT_ON_ACCEPT_CHANGES) {
885 // do commit/rollback's here
886 if (!conflict) {
887 tWriter = (TransactionalWriter)rowSetWriter;
888 tWriter.rollback();
889 success = false;
890 } else {
891 tWriter = (TransactionalWriter)rowSetWriter;
892 if (tWriter instanceof CachedRowSetWriter) {
893 ((CachedRowSetWriter)tWriter).commit(this, updateOnInsert);
894 } else {
895 tWriter.commit();
896 }
897
898 success = true;
899 }
900 }
901
902 if (success == true) {
903 setOriginal();
904 } else if (!(success) && !(this.COMMIT_ON_ACCEPT_CHANGES)) {
905 throw new SyncProviderException(resBundle.handleGetObject("cachedrowsetimpl.accfailed").toString());
906 }
907
908 } catch (SyncProviderException spe) {
909 throw spe;
910 } catch (SQLException e) {
911 e.printStackTrace();
912 throw new SyncProviderException(e.getMessage());
913 } catch (SecurityException e) {
914 throw new SyncProviderException(e.getMessage());
915 }
916 }
917
918 /**
919 * Propagates all row update, insert, and delete changes to the
920 * data source backing this <code>CachedRowSetImpl</code> object
921 * using the given <code>Connection</code> object.
922 * <P>
923 * The reference implementation <code>RIOptimisticProvider</code>
924 * modifies its synchronization to a write back function given
925 * the updated connection
926 * The reference implementation modifies its synchronization behaviour
927 * via the <code>SyncProvider</code> to ensure the synchronization
928 * occurs according to the updated JDBC <code>Connection</code>
929 * properties.
930 *
931 * @param con a standard JDBC <code>Connection</code> object
932 * @throws SQLException if the cursor is on the insert row or the underlying
933 * synchronization provider fails to commit the updates
934 * back to the data source
935 * @see #acceptChanges
936 * @see javax.sql.RowSetWriter
937 * @see javax.sql.rowset.spi.SyncFactory
938 * @see javax.sql.rowset.spi.SyncProvider
939 */
940 public void acceptChanges(Connection con) throws SyncProviderException{
941
942 setConnection(con);
943 acceptChanges();
944
945 }
946
947 /**
948 * Restores this <code>CachedRowSetImpl</code> object to its original state,
949 * that is, its state before the last set of changes.
950 * <P>
951 * Before returning, this method moves the cursor before the first row
952 * and sends a <code>rowSetChanged</code> event to all registered
953 * listeners.
954 * @throws SQLException if an error is occurs rolling back the RowSet
955 * state to the definied original value.
956 * @see javax.sql.RowSetListener#rowSetChanged
957 */
958 public void restoreOriginal() throws SQLException {
959 Row currentRow;
960 for (Iterator i = rvh.iterator(); i.hasNext();) {
961 currentRow = (Row)i.next();
962 if (currentRow.getInserted() == true) {
963 i.remove();
964 --numRows;
965 } else {
966 if (currentRow.getDeleted() == true) {
967 currentRow.clearDeleted();
968 }
969 if (currentRow.getUpdated() == true) {
970 currentRow.clearUpdated();
971 }
972 }
973 }
974 // move to before the first
975 cursorPos = 0;
976
977 // notify any listeners
978 notifyRowSetChanged();
979 }
980
981 /**
982 * Releases the current contents of this <code>CachedRowSetImpl</code>
983 * object and sends a <code>rowSetChanged</code> event object to all
984 * registered listeners.
985 *
986 * @throws SQLException if an error occurs flushing the contents of
987 * RowSet.
988 * @see javax.sql.RowSetListener#rowSetChanged
989 */
990 public void release() throws SQLException {
991 initContainer();
992 notifyRowSetChanged();
993 }
994
995 /**
996 * Cancels deletion of the current row and notifies listeners that
997 * a row has changed.
998 * <P>
999 * Note: This method can be ignored if deleted rows are not being shown,
1000 * which is the normal case.
1001 *
1002 * @throws SQLException if the cursor is not on a valid row
1003 */
1004 public void undoDelete() throws SQLException {
1005 if (getShowDeleted() == false) {
1006 return;
1007 }
1008 // make sure we are on a row
1009 checkCursor();
1010
1011 // don't want this to happen...
1012 if (onInsertRow == true) {
1013 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1014 }
1015
1016 Row currentRow = (Row)getCurrentRow();
1017 if (currentRow.getDeleted() == true) {
1018 currentRow.clearDeleted();
1019 --numDeleted;
1020 notifyRowChanged();
1021 }
1022 }
1023
1024 /**
1025 * Immediately removes the current row from this
1026 * <code>CachedRowSetImpl</code> object if the row has been inserted, and
1027 * also notifies listeners the a row has changed. An exception is thrown
1028 * if the row is not a row that has been inserted or the cursor is before
1029 * the first row, after the last row, or on the insert row.
1030 * <P>
1031 * This operation cannot be undone.
1032 *
1033 * @throws SQLException if an error occurs,
1034 * the cursor is not on a valid row,
1035 * or the row has not been inserted
1036 */
1037 public void undoInsert() throws SQLException {
1038 // make sure we are on a row
1039 checkCursor();
1040
1041 // don't want this to happen...
1042 if (onInsertRow == true) {
1043 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1044 }
1045
1046 Row currentRow = (Row)getCurrentRow();
1047 if (currentRow.getInserted() == true) {
1048 rvh.remove(cursorPos-1);
1049 --numRows;
1050 notifyRowChanged();
1051 } else {
1052 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.illegalop").toString());
1053 }
1054 }
1055
1056 /**
1057 * Immediately reverses the last update operation if the
1058 * row has been modified. This method can be
1059 * called to reverse updates on a all columns until all updates in a row have
1060 * been rolled back to their originating state since the last synchronization
1061 * (<code>acceptChanges</code>) or population. This method may also be called
1062 * while performing updates to the insert row.
1063 * <P>
1064 * <code>undoUpdate</code may be called at any time during the life-time of a
1065 * rowset, however after a synchronization has occurs this method has no
1066 * affect until further modification to the RowSet data occurs.
1067 *
1068 * @throws SQLException if cursor is before the first row, after the last
1069 * row in rowset.
1070 * @see #undoDelete
1071 * @see #undoInsert
1072 * @see java.sql.ResultSet#cancelRowUpdates
1073 */
1074 public void undoUpdate() throws SQLException {
1075 // if on insert row, cancel the insert row
1076 // make the insert row flag,
1077 // cursorPos back to the current row
1078 moveToCurrentRow();
1079
1080 // else if not on insert row
1081 // call undoUpdate or undoInsert
1082 undoDelete();
1083
1084 undoInsert();
1085
1086 }
1087
1088 //--------------------------------------------------------------------
1089 // Views
1090 //--------------------------------------------------------------------
1091
1092 /**
1093 * Returns a new <code>RowSet</code> object backed by the same data as
1094 * that of this <code>CachedRowSetImpl</code> object and sharing a set of cursors
1095 * with it. This allows cursors to interate over a shared set of rows, providing
1096 * multiple views of the underlying data.
1097 *
1098 * @return a <code>RowSet</code> object that is a copy of this <code>CachedRowSetImpl</code>
1099 * object and shares a set of cursors with it
1100 * @throws SQLException if an error occurs or cloning is
1101 * not supported
1102 * @see javax.sql.RowSetEvent
1103 * @see javax.sql.RowSetListener
1104 */
1105 public RowSet createShared() throws SQLException {
1106 RowSet clone;
1107 try {
1108 clone = (RowSet)clone();
1109 } catch (CloneNotSupportedException ex) {
1110 throw new SQLException(ex.getMessage());
1111 }
1112 return clone;
1113 }
1114
1115 /**
1116 * Returns a new <code>RowSet</code> object containing by the same data
1117 * as this <code>CachedRowSetImpl</code> object. This method
1118 * differs from the method <code>createCopy</code> in that it throws a
1119 * <code>CloneNotSupportedException</code> object instead of an
1120 * <code>SQLException</code> object, as the method <code>createShared</code>
1121 * does. This <code>clone</code>
1122 * method is called internally by the method <code>createShared</code>,
1123 * which catches the <code>CloneNotSupportedException</code> object
1124 * and in turn throws a new <code>SQLException</code> object.
1125 *
1126 * @return a copy of this <code>CachedRowSetImpl</code> object
1127 * @throws CloneNotSupportedException if an error occurs when
1128 * attempting to clone this <code>CachedRowSetImpl</code> object
1129 * @see #createShared
1130 */
1131 protected Object clone() throws CloneNotSupportedException {
1132 return (super.clone());
1133 }
1134
1135 /**
1136 * Creates a <code>RowSet</code> object that is a deep copy of
1137 * this <code>CachedRowSetImpl</code> object's data, including
1138 * constraints. Updates made
1139 * on a copy are not visible to the original rowset;
1140 * a copy of a rowset is completely independent from the original.
1141 * <P>
1142 * Making a copy saves the cost of creating an identical rowset
1143 * from first principles, which can be quite expensive.
1144 * For example, it can eliminate the need to query a
1145 * remote database server.
1146 * @return a new <code>CachedRowSet</code> object that is a deep copy
1147 * of this <code>CachedRowSet</code> object and is
1148 * completely independent from this <code>CachedRowSetImpl</code>
1149 * object.
1150 * @throws SQLException if an error occurs in generating the copy of this
1151 * of the <code>CachedRowSetImpl</code>
1152 * @see #createShared
1153 * @see javax.sql.RowSetEvent
1154 * @see javax.sql.RowSetListener
1155 */
1156 public CachedRowSet createCopy() throws SQLException {
1157 ObjectOutputStream out;
1158 ByteArrayOutputStream bOut = new ByteArrayOutputStream();
1159 try {
1160 out = new ObjectOutputStream(bOut);
1161 out.writeObject(this);
1162 } catch (IOException ex) {
1163 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1164 }
1165
1166 ObjectInputStream in;
1167
1168 try {
1169 ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
1170 in = new ObjectInputStream(bIn);
1171 } catch (StreamCorruptedException ex) {
1172 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1173 } catch (IOException ex) {
1174 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1175 }
1176
1177 try {
1178 //return ((CachedRowSet)(in.readObject()));
1179 CachedRowSetImpl crsTemp = (CachedRowSetImpl)in.readObject();
1180 crsTemp.resBundle = this.resBundle;
1181 return ((CachedRowSet)crsTemp);
1182
1183 } catch (ClassNotFoundException ex) {
1184 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1185 } catch (OptionalDataException ex) {
1186 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1187 } catch (IOException ex) {
1188 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage()));
1189 }
1190 }
1191
1192 /**
1193 * Creates a <code>RowSet</code> object that is a copy of
1194 * this <code>CachedRowSetImpl</code> object's table structure
1195 * and the constraints only.
1196 * There will be no data in the object being returned.
1197 * Updates made on a copy are not visible to the original rowset.
1198 * <P>
1199 * This helps in getting the underlying XML schema which can
1200 * be used as the basis for populating a <code>WebRowSet</code>.
1201 *
1202 * @return a new <code>CachedRowSet</code> object that is a copy
1203 * of this <code>CachedRowSetImpl</code> object's schema and
1204 * retains all the constraints on the original rowset but contains
1205 * no data
1206 * @throws SQLException if an error occurs in generating the copy
1207 * of the <code>CachedRowSet</code> object
1208 * @see #createShared
1209 * @see #createCopy
1210 * @see #createCopyNoConstraints
1211 * @see javax.sql.RowSetEvent
1212 * @see javax.sql.RowSetListener
1213 */
1214 public CachedRowSet createCopySchema() throws SQLException {
1215 // Copy everything except data i.e all constraints
1216
1217 // Store the number of rows of "this"
1218 // and make numRows equals zero.
1219 // and make data also zero.
1220 int nRows = numRows;
1221 numRows = 0;
1222
1223 CachedRowSet crs = this.createCopy();
1224
1225 // reset this object back to number of rows.
1226 numRows = nRows;
1227
1228 return crs;
1229 }
1230
1231 /**
1232 * Creates a <code>CachedRowSet</code> object that is a copy of
1233 * this <code>CachedRowSetImpl</code> object's data only.
1234 * All constraints set in this object will not be there
1235 * in the returning object. Updates made
1236 * on a copy are not visible to the original rowset.
1237 *
1238 * @return a new <code>CachedRowSet</code> object that is a deep copy
1239 * of this <code>CachedRowSetImpl</code> object and is
1240 * completely independent from this <code>CachedRowSetImpl</code> object
1241 * @throws SQLException if an error occurs in generating the copy of the
1242 * of the <code>CachedRowSet</code>
1243 * @see #createShared
1244 * @see #createCopy
1245 * @see #createCopySchema
1246 * @see javax.sql.RowSetEvent
1247 * @see javax.sql.RowSetListener
1248 */
1249 public CachedRowSet createCopyNoConstraints() throws SQLException {
1250 // Copy the whole data ONLY without any constraints.
1251 CachedRowSetImpl crs;
1252 crs = (CachedRowSetImpl)this.createCopy();
1253
1254 crs.initProperties();
1255 try {
1256 crs.unsetMatchColumn(crs.getMatchColumnIndexes());
1257 } catch(SQLException sqle) {
1258 //do nothing, if the setMatchColumn is not set.
1259 }
1260
1261 try {
1262 crs.unsetMatchColumn(crs.getMatchColumnNames());
1263 } catch(SQLException sqle) {
1264 //do nothing, if the setMatchColumn is not set.
1265 }
1266
1267 return crs;
1268 }
1269
1270 /**
1271 * Converts this <code>CachedRowSetImpl</code> object to a collection
1272 * of tables. The sample implementation utilitizes the <code>TreeMap</code>
1273 * collection type.
1274 * This class guarantees that the map will be in ascending key order,
1275 * sorted according to the natural order for the key's class.
1276 *
1277 * @return a <code>Collection</code> object consisting of tables,
1278 * each of which is a copy of a row in this
1279 * <code>CachedRowSetImpl</code> object
1280 * @throws SQLException if an error occurs in generating the collection
1281 * @see #toCollection(int)
1282 * @see #toCollection(String)
1283 * @see java.util.TreeMap
1284 */
1285 public Collection<?> toCollection() throws SQLException {
1286
1287 TreeMap<Integer, Object> tMap = new TreeMap<>();
1288
1289 for (int i = 0; i<numRows; i++) {
1290 tMap.put(Integer.valueOf(i), rvh.get(i));
1291 }
1292
1293 return (tMap.values());
1294 }
1295
1296 /**
1297 * Returns the specified column of this <code>CachedRowSetImpl</code> object
1298 * as a <code>Collection</code> object. This method makes a copy of the
1299 * column's data and utilitizes the <code>Vector</code> to establish the
1300 * collection. The <code>Vector</code> class implements a growable array
1301 * objects allowing the individual components to be accessed using an
1302 * an integer index similar to that of an array.
1303 *
1304 * @return a <code>Collection</code> object that contains the value(s)
1305 * stored in the specified column of this
1306 * <code>CachedRowSetImpl</code>
1307 * object
1308 * @throws SQLException if an error occurs generated the collection; or
1309 * an invalid column is provided.
1310 * @see #toCollection()
1311 * @see #toCollection(String)
1312 * @see java.util.Vector
1313 */
1314 public Collection<?> toCollection(int column) throws SQLException {
1315
1316 int nRows = numRows;
1317 Vector<Object> vec = new Vector<>(nRows);
1318
1319 // create a copy
1320 CachedRowSetImpl crsTemp;
1321 crsTemp = (CachedRowSetImpl) this.createCopy();
1322
1323 while(nRows!=0) {
1324 crsTemp.next();
1325 vec.add(crsTemp.getObject(column));
1326 nRows--;
1327 }
1328
1329 return (Collection)vec;
1330 }
1331
1332 /**
1333 * Returns the specified column of this <code>CachedRowSetImpl</code> object
1334 * as a <code>Collection</code> object. This method makes a copy of the
1335 * column's data and utilitizes the <code>Vector</code> to establish the
1336 * collection. The <code>Vector</code> class implements a growable array
1337 * objects allowing the individual components to be accessed using an
1338 * an integer index similar to that of an array.
1339 *
1340 * @return a <code>Collection</code> object that contains the value(s)
1341 * stored in the specified column of this
1342 * <code>CachedRowSetImpl</code>
1343 * object
1344 * @throws SQLException if an error occurs generated the collection; or
1345 * an invalid column is provided.
1346 * @see #toCollection()
1347 * @see #toCollection(int)
1348 * @see java.util.Vector
1349 */
1350 public Collection<?> toCollection(String column) throws SQLException {
1351 return toCollection(getColIdxByName(column));
1352 }
1353
1354 //--------------------------------------------------------------------
1355 // Advanced features
1356 //--------------------------------------------------------------------
1357
1358
1359 /**
1360 * Returns the <code>SyncProvider</code> implementation being used
1361 * with this <code>CachedRowSetImpl</code> implementation rowset.
1362 *
1363 * @return the SyncProvider used by the rowset. If not provider was
1364 * set when the rowset was instantiated, the reference
1365 * implementation (default) provider is returned.
1366 * @throws SQLException if error occurs while return the
1367 * <code>SyncProvider</code> instance.
1368 */
1369 public SyncProvider getSyncProvider() throws SQLException {
1370 return provider;
1371 }
1372
1373 /**
1374 * Sets the active <code>SyncProvider</code> and attempts to load
1375 * load the new provider using the <code>SyncFactory</code> SPI.
1376 *
1377 * @throws SQLException if an error occurs while resetting the
1378 * <code>SyncProvider</code>.
1379 */
1380 public void setSyncProvider(String providerStr) throws SQLException {
1381 provider =
1382 (SyncProvider)SyncFactory.getInstance(providerStr);
1383
1384 rowSetReader = provider.getRowSetReader();
1385 rowSetWriter = provider.getRowSetWriter();
1386 }
1387
1388
1389 //-----------------
1390 // methods inherited from RowSet
1391 //-----------------
1392
1393
1394
1395
1396
1397
1398 //---------------------------------------------------------------------
1399 // Reading and writing data
1400 //---------------------------------------------------------------------
1401
1402 /**
1403 * Populates this <code>CachedRowSetImpl</code> object with data.
1404 * This form of the method uses the rowset's user, password, and url or
1405 * data source name properties to create a database
1406 * connection. If properties that are needed
1407 * have not been set, this method will throw an exception.
1408 * <P>
1409 * Another form of this method uses an existing JDBC <code>Connection</code>
1410 * object instead of creating a new one; therefore, it ignores the
1411 * properties used for establishing a new connection.
1412 * <P>
1413 * The query specified by the command property is executed to create a
1414 * <code>ResultSet</code> object from which to retrieve data.
1415 * The current contents of the rowset are discarded, and the
1416 * rowset's metadata is also (re)set. If there are outstanding updates,
1417 * they are also ignored.
1418 * <P>
1419 * The method <code>execute</code> closes any database connections that it
1420 * creates.
1421 *
1422 * @throws SQLException if an error occurs or the
1423 * necessary properties have not been set
1424 */
1425 public void execute() throws SQLException {
1426 execute(null);
1427 }
1428
1429
1430
1431 //-----------------------------------
1432 // Methods inherited from ResultSet
1433 //-----------------------------------
1434
1435 /**
1436 * Moves the cursor down one row from its current position and
1437 * returns <code>true</code> if the new cursor position is a
1438 * valid row.
1439 * The cursor for a new <code>ResultSet</code> object is initially
1440 * positioned before the first row. The first call to the method
1441 * <code>next</code> moves the cursor to the first row, making it
1442 * the current row; the second call makes the second row the
1443 * current row, and so on.
1444 *
1445 * <P>If an input stream from the previous row is open, it is
1446 * implicitly closed. The <code>ResultSet</code> object's warning
1447 * chain is cleared when a new row is read.
1448 *
1449 * @return <code>true</code> if the new current row is valid;
1450 * <code>false</code> if there are no more rows
1451 * @throws SQLException if an error occurs or
1452 * the cursor is not positioned in the rowset, before
1453 * the first row, or after the last row
1454 */
1455 public boolean next() throws SQLException {
1456 /*
1457 * make sure things look sane. The cursor must be
1458 * positioned in the rowset or before first (0) or
1459 * after last (numRows + 1)
1460 */
1461 if (cursorPos < 0 || cursorPos >= numRows + 1) {
1462 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1463 }
1464 // now move and notify
1465 boolean ret = this.internalNext();
1466 notifyCursorMoved();
1467
1468 return ret;
1469 }
1470
1471 /**
1472 * Moves this <code>CachedRowSetImpl</code> object's cursor to the next
1473 * row and returns <code>true</code> if the cursor is still in the rowset;
1474 * returns <code>false</code> if the cursor has moved to the position after
1475 * the last row.
1476 * <P>
1477 * This method handles the cases where the cursor moves to a row that
1478 * has been deleted.
1479 * If this rowset shows deleted rows and the cursor moves to a row
1480 * that has been deleted, this method moves the cursor to the next
1481 * row until the cursor is on a row that has not been deleted.
1482 * <P>
1483 * The method <code>internalNext</code> is called by methods such as
1484 * <code>next</code>, <code>absolute</code>, and <code>relative</code>,
1485 * and, as its name implies, is only called internally.
1486 * <p>
1487 * This is a implementation only method and is not required as a standard
1488 * implementation of the <code>CachedRowSet</code> interface.
1489 *
1490 * @return <code>true</code> if the cursor is on a valid row in this
1491 * rowset; <code>false</code> if it is after the last row
1492 * @throws SQLException if an error occurs
1493 */
1494 protected boolean internalNext() throws SQLException {
1495 boolean ret = false;
1496
1497 do {
1498 if (cursorPos < numRows) {
1499 ++cursorPos;
1500 ret = true;
1501 } else if (cursorPos == numRows) {
1502 // increment to after last
1503 ++cursorPos;
1504 ret = false;
1505 break;
1506 }
1507 } while ((getShowDeleted() == false) && (rowDeleted() == true));
1508
1509 /* each call to internalNext may increment cursorPos multiple
1510 * times however, the absolutePos only increments once per call.
1511 */
1512 if (ret == true)
1513 absolutePos++;
1514 else
1515 absolutePos = 0;
1516
1517 return ret;
1518 }
1519
1520 /**
1521 * Closes this <code>CachedRowSetImpl</code> objecy and releases any resources
1522 * it was using.
1523 *
1524 * @throws SQLException if an error occurs when releasing any resources in use
1525 * by this <code>CachedRowSetImpl</code> object
1526 */
1527 public void close() throws SQLException {
1528
1529 // close all data structures holding
1530 // the disconnected rowset
1531
1532 cursorPos = 0;
1533 absolutePos = 0;
1534 numRows = 0;
1535 numDeleted = 0;
1536
1537 // set all insert(s), update(s) & delete(s),
1538 // if at all, to their initial values.
1539 initProperties();
1540
1541 // clear the vector of it's present contents
1542 rvh.clear();
1543
1544 // this will make it eligible for gc
1545 // rvh = null;
1546 }
1547
1548 /**
1549 * Reports whether the last column read was SQL <code>NULL</code>.
1550 * Note that you must first call the method <code>getXXX</code>
1551 * on a column to try to read its value and then call the method
1552 * <code>wasNull</code> to determine whether the value was
1553 * SQL <code>NULL</code>.
1554 *
1555 * @return <code>true</code> if the value in the last column read
1556 * was SQL <code>NULL</code>; <code>false</code> otherwise
1557 * @throws SQLException if an error occurs
1558 */
1559 public boolean wasNull() throws SQLException {
1560 return lastValueNull;
1561 }
1562
1563 /**
1564 * Sets the field <code>lastValueNull</code> to the given
1565 * <code>boolean</code> value.
1566 *
1567 * @param value <code>true</code> to indicate that the value of
1568 * the last column read was SQL <code>NULL</code>;
1569 * <code>false</code> to indicate that it was not
1570 */
1571 private void setLastValueNull(boolean value) {
1572 lastValueNull = value;
1573 }
1574
1575 // Methods for accessing results by column index
1576
1577 /**
1578 * Checks to see whether the given index is a valid column number
1579 * in this <code>CachedRowSetImpl</code> object and throws
1580 * an <code>SQLException</code> if it is not. The index is out of bounds
1581 * if it is less than <code>1</code> or greater than the number of
1582 * columns in this rowset.
1583 * <P>
1584 * This method is called internally by the <code>getXXX</code> and
1585 * <code>updateXXX</code> methods.
1586 *
1587 * @param idx the number of a column in this <code>CachedRowSetImpl</code>
1588 * object; must be between <code>1</code> and the number of
1589 * rows in this rowset
1590 * @throws SQLException if the given index is out of bounds
1591 */
1592 private void checkIndex(int idx) throws SQLException {
1593 if (idx < 1 || idx > RowSetMD.getColumnCount()) {
1594 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcol").toString());
1595 }
1596 }
1597
1598 /**
1599 * Checks to see whether the cursor for this <code>CachedRowSetImpl</code>
1600 * object is on a row in the rowset and throws an
1601 * <code>SQLException</code> if it is not.
1602 * <P>
1603 * This method is called internally by <code>getXXX</code> methods, by
1604 * <code>updateXXX</code> methods, and by methods that update, insert,
1605 * or delete a row or that cancel a row update, insert, or delete.
1606 *
1607 * @throws SQLException if the cursor for this <code>CachedRowSetImpl</code>
1608 * object is not on a valid row
1609 */
1610 private void checkCursor() throws SQLException {
1611 if (isAfterLast() == true || isBeforeFirst() == true) {
1612 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
1613 }
1614 }
1615
1616 /**
1617 * Returns the column number of the column with the given name in this
1618 * <code>CachedRowSetImpl</code> object. This method throws an
1619 * <code>SQLException</code> if the given name is not the name of
1620 * one of the columns in this rowset.
1621 *
1622 * @param name a <code>String</code> object that is the name of a column in
1623 * this <code>CachedRowSetImpl</code> object
1624 * @throws SQLException if the given name does not match the name of one of
1625 * the columns in this rowset
1626 */
1627 private int getColIdxByName(String name) throws SQLException {
1628 RowSetMD = (RowSetMetaDataImpl)this.getMetaData();
1629 int cols = RowSetMD.getColumnCount();
1630
1631 for (int i=1; i <= cols; ++i) {
1632 String colName = RowSetMD.getColumnName(i);
1633 if (colName != null)
1634 if (name.equalsIgnoreCase(colName))
1635 return (i);
1636 else
1637 continue;
1638 }
1639 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalcolnm").toString());
1640
1641 }
1642
1643 /**
1644 * Returns the insert row or the current row of this
1645 * <code>CachedRowSetImpl</code>object.
1646 *
1647 * @return the <code>Row</code> object on which this <code>CachedRowSetImpl</code>
1648 * objects's cursor is positioned
1649 */
1650 protected BaseRow getCurrentRow() {
1651 if (onInsertRow == true) {
1652 return (BaseRow)insertRow;
1653 } else {
1654 return (BaseRow)(rvh.get(cursorPos - 1));
1655 }
1656 }
1657
1658 /**
1659 * Removes the row on which the cursor is positioned.
1660 * <p>
1661 * This is a implementation only method and is not required as a standard
1662 * implementation of the <code>CachedRowSet</code> interface.
1663 *
1664 * @throws SQLException if the cursor is positioned on the insert
1665 * row
1666 */
1667 protected void removeCurrentRow() {
1668 ((Row)getCurrentRow()).setDeleted();
1669 rvh.remove(cursorPos - 1);
1670 --numRows;
1671 }
1672
1673
1674 /**
1675 * Retrieves the value of the designated column in the current row
1676 * of this <code>CachedRowSetImpl</code> object as a
1677 * <code>String</code> object.
1678 *
1679 * @param columnIndex the first column is <code>1</code>, the second
1680 * is <code>2</code>, and so on; must be <code>1</code> or larger
1681 * and equal to or less than the number of columns in the rowset
1682 * @return the column value; if the value is SQL <code>NULL</code>, the
1683 * result is <code>null</code>
1684 * @throws SQLException if (1) the given column index is out of bounds,
1685 * (2) the cursor is not on one of this rowset's rows or its
1686 * insert row, or (3) the designated column does not store an
1687 * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, REAL,
1688 * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, <b>CHAR</b>, <b>VARCHAR</b></code>
1689 * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1690 * recommended return type.
1691 */
1692 public String getString(int columnIndex) throws SQLException {
1693 Object value;
1694
1695 // sanity check.
1696 checkIndex(columnIndex);
1697 // make sure the cursor is on a valid row
1698 checkCursor();
1699
1700 setLastValueNull(false);
1701 value = getCurrentRow().getColumnObject(columnIndex);
1702
1703 // check for SQL NULL
1704 if (value == null) {
1705 setLastValueNull(true);
1706 return null;
1707 }
1708
1709 return value.toString();
1710 }
1711
1712 /**
1713 * Retrieves the value of the designated column in the current row
1714 * of this <code>CachedRowSetImpl</code> object as a
1715 * <code>boolean</code> value.
1716 *
1717 * @param columnIndex the first column is <code>1</code>, the second
1718 * is <code>2</code>, and so on; must be <code>1</code> or larger
1719 * and equal to or less than the number of columns in the rowset
1720 * @return the column value as a <code>boolean</code> in the Java progamming language;
1721 * if the value is SQL <code>NULL</code>, the result is <code>false</code>
1722 * @throws SQLException if (1) the given column index is out of bounds,
1723 * (2) the cursor is not on one of this rowset's rows or its
1724 * insert row, or (3) the designated column does not store an
1725 * SQL <code>BOOLEAN</code> value
1726 * @see #getBoolean(String)
1727 */
1728 public boolean getBoolean(int columnIndex) throws SQLException {
1729 Object value;
1730
1731 // sanity check.
1732 checkIndex(columnIndex);
1733 // make sure the cursor is on a valid row
1734 checkCursor();
1735
1736 setLastValueNull(false);
1737 value = getCurrentRow().getColumnObject(columnIndex);
1738
1739 // check for SQL NULL
1740 if (value == null) {
1741 setLastValueNull(true);
1742 return false;
1743 }
1744
1745 // check for Boolean...
1746 if (value instanceof Boolean) {
1747 return ((Boolean)value).booleanValue();
1748 }
1749
1750 // convert to a Double and compare to zero
1751 try {
1752 Double d = new Double(value.toString());
1753 if (d.compareTo(new Double((double)0)) == 0) {
1754 return false;
1755 } else {
1756 return true;
1757 }
1758 } catch (NumberFormatException ex) {
1759 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.boolfail").toString(),
1760 new Object[] {value.toString().trim(), columnIndex}));
1761 }
1762 }
1763
1764 /**
1765 * Retrieves the value of the designated column in the current row
1766 * of this <code>CachedRowSetImpl</code> object as a
1767 * <code>byte</code> value.
1768 *
1769 * @param columnIndex the first column is <code>1</code>, the second
1770 * is <code>2</code>, and so on; must be <code>1</code> or larger
1771 * and equal to or less than the number of columns in the rowset
1772 * @return the column value as a <code>byte</code> in the Java programming
1773 * language; if the value is SQL <code>NULL</code>, the result is <code>0</code>
1774 * @throws SQLException if (1) the given column index is out of bounds,
1775 * (2) the cursor is not on one of this rowset's rows or its
1776 * insert row, or (3) the designated column does not store an
1777 * SQL <code><b>TINYINT</b>, SMALLINT, INTEGER, BIGINT, REAL,
1778 * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1779 * or <code>LONGVARCHAR</code> value. The bold SQL type
1780 * designates the recommended return type.
1781 * @see #getByte(String)
1782 */
1783 public byte getByte(int columnIndex) throws SQLException {
1784 Object value;
1785
1786 // sanity check.
1787 checkIndex(columnIndex);
1788 // make sure the cursor is on a valid row
1789 checkCursor();
1790
1791 setLastValueNull(false);
1792 value = getCurrentRow().getColumnObject(columnIndex);
1793
1794 // check for SQL NULL
1795 if (value == null) {
1796 setLastValueNull(true);
1797 return (byte)0;
1798 }
1799 try {
1800 return ((Byte.valueOf(value.toString())).byteValue());
1801 } catch (NumberFormatException ex) {
1802 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.bytefail").toString(),
1803 new Object[] {value.toString().trim(), columnIndex}));
1804 }
1805 }
1806
1807 /**
1808 * Retrieves the value of the designated column in the current row
1809 * of this <code>CachedRowSetImpl</code> object as a
1810 * <code>short</code> value.
1811 *
1812 * @param columnIndex the first column is <code>1</code>, the second
1813 * is <code>2</code>, and so on; must be <code>1</code> or larger
1814 * and equal to or less than the number of columns in the rowset
1815 * @return the column value; if the value is SQL <code>NULL</code>, the
1816 * result is <code>0</code>
1817 * @throws SQLException if (1) the given column index is out of bounds,
1818 * (2) the cursor is not on one of this rowset's rows or its
1819 * insert row, or (3) the designated column does not store an
1820 * SQL <code>TINYINT, <b>SMALLINT</b>, INTEGER, BIGINT, REAL
1821 * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1822 * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1823 * recommended return type.
1824 * @see #getShort(String)
1825 */
1826 public short getShort(int columnIndex) throws SQLException {
1827 Object value;
1828
1829 // sanity check.
1830 checkIndex(columnIndex);
1831 // make sure the cursor is on a valid row
1832 checkCursor();
1833
1834 setLastValueNull(false);
1835 value = getCurrentRow().getColumnObject(columnIndex);
1836
1837 // check for SQL NULL
1838 if (value == null) {
1839 setLastValueNull(true);
1840 return (short)0;
1841 }
1842
1843 try {
1844 return ((Short.valueOf(value.toString().trim())).shortValue());
1845 } catch (NumberFormatException ex) {
1846 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.shortfail").toString(),
1847 new Object[] {value.toString().trim(), columnIndex}));
1848 }
1849 }
1850
1851 /**
1852 * Retrieves the value of the designated column in the current row
1853 * of this <code>CachedRowSetImpl</code> object as an
1854 * <code>int</code> value.
1855 *
1856 * @param columnIndex the first column is <code>1</code>, the second
1857 * is <code>2</code>, and so on; must be <code>1</code> or larger
1858 * and equal to or less than the number of columns in the rowset
1859 * @return the column value; if the value is SQL <code>NULL</code>, the
1860 * result is <code>0</code>
1861 * @throws SQLException if (1) the given column index is out of bounds,
1862 * (2) the cursor is not on one of this rowset's rows or its
1863 * insert row, or (3) the designated column does not store an
1864 * SQL <code>TINYINT, SMALLINT, <b>INTEGER</b>, BIGINT, REAL
1865 * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1866 * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1867 * recommended return type.
1868 */
1869 public int getInt(int columnIndex) throws SQLException {
1870 Object value;
1871
1872 // sanity check.
1873 checkIndex(columnIndex);
1874 // make sure the cursor is on a valid row
1875 checkCursor();
1876
1877 setLastValueNull(false);
1878 value = getCurrentRow().getColumnObject(columnIndex);
1879
1880 // check for SQL NULL
1881 if (value == null) {
1882 setLastValueNull(true);
1883 return (int)0;
1884 }
1885
1886 try {
1887 return ((Integer.valueOf(value.toString().trim())).intValue());
1888 } catch (NumberFormatException ex) {
1889 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.intfail").toString(),
1890 new Object[] {value.toString().trim(), columnIndex}));
1891 }
1892 }
1893
1894 /**
1895 * Retrieves the value of the designated column in the current row
1896 * of this <code>CachedRowSetImpl</code> object as a
1897 * <code>long</code> value.
1898 *
1899 * @param columnIndex the first column is <code>1</code>, the second
1900 * is <code>2</code>, and so on; must be <code>1</code> or larger
1901 * and equal to or less than the number of columns in the rowset
1902 * @return the column value; if the value is SQL <code>NULL</code>, the
1903 * result is <code>0</code>
1904 * @throws SQLException if (1) the given column index is out of bounds,
1905 * (2) the cursor is not on one of this rowset's rows or its
1906 * insert row, or (3) the designated column does not store an
1907 * SQL <code>TINYINT, SMALLINT, INTEGER, <b>BIGINT</b>, REAL
1908 * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1909 * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1910 * recommended return type.
1911 * @see #getLong(String)
1912 */
1913 public long getLong(int columnIndex) throws SQLException {
1914 Object value;
1915
1916 // sanity check.
1917 checkIndex(columnIndex);
1918 // make sure the cursor is on a valid row
1919 checkCursor();
1920
1921 setLastValueNull(false);
1922 value = getCurrentRow().getColumnObject(columnIndex);
1923
1924 // check for SQL NULL
1925 if (value == null) {
1926 setLastValueNull(true);
1927 return (long)0;
1928 }
1929 try {
1930 return ((Long.valueOf(value.toString().trim())).longValue());
1931 } catch (NumberFormatException ex) {
1932 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.longfail").toString(),
1933 new Object[] {value.toString().trim(), columnIndex}));
1934 }
1935 }
1936
1937 /**
1938 * Retrieves the value of the designated column in the current row
1939 * of this <code>CachedRowSetImpl</code> object as a
1940 * <code>float</code> value.
1941 *
1942 * @param columnIndex the first column is <code>1</code>, the second
1943 * is <code>2</code>, and so on; must be <code>1</code> or larger
1944 * and equal to or less than the number of columns in the rowset
1945 * @return the column value; if the value is SQL <code>NULL</code>, the
1946 * result is <code>0</code>
1947 * @throws SQLException if (1) the given column index is out of bounds,
1948 * (2) the cursor is not on one of this rowset's rows or its
1949 * insert row, or (3) the designated column does not store an
1950 * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, <b>REAL</b>,
1951 * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1952 * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1953 * recommended return type.
1954 * @see #getFloat(String)
1955 */
1956 public float getFloat(int columnIndex) throws SQLException {
1957 Object value;
1958
1959 // sanity check.
1960 checkIndex(columnIndex);
1961 // make sure the cursor is on a valid row
1962 checkCursor();
1963
1964 setLastValueNull(false);
1965 value = getCurrentRow().getColumnObject(columnIndex);
1966
1967 // check for SQL NULL
1968 if (value == null) {
1969 setLastValueNull(true);
1970 return (float)0;
1971 }
1972 try {
1973 return ((new Float(value.toString())).floatValue());
1974 } catch (NumberFormatException ex) {
1975 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.floatfail").toString(),
1976 new Object[] {value.toString().trim(), columnIndex}));
1977 }
1978 }
1979
1980 /**
1981 * Retrieves the value of the designated column in the current row
1982 * of this <code>CachedRowSetImpl</code> object as a
1983 * <code>double</code> value.
1984 *
1985 * @param columnIndex the first column is <code>1</code>, the second
1986 * is <code>2</code>, and so on; must be <code>1</code> or larger
1987 * and equal to or less than the number of columns in the rowset
1988 * @return the column value; if the value is SQL <code>NULL</code>, the
1989 * result is <code>0</code>
1990 * @throws SQLException if (1) the given column index is out of bounds,
1991 * (2) the cursor is not on one of this rowset's rows or its
1992 * insert row, or (3) the designated column does not store an
1993 * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, REAL,
1994 * <b>FLOAT</b>, <b>DOUBLE</b>, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
1995 * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
1996 * recommended return type.
1997 * @see #getDouble(String)
1998 *
1999 */
2000 public double getDouble(int columnIndex) throws SQLException {
2001 Object value;
2002
2003 // sanity check.
2004 checkIndex(columnIndex);
2005 // make sure the cursor is on a valid row
2006 checkCursor();
2007
2008 setLastValueNull(false);
2009 value = getCurrentRow().getColumnObject(columnIndex);
2010
2011 // check for SQL NULL
2012 if (value == null) {
2013 setLastValueNull(true);
2014 return (double)0;
2015 }
2016 try {
2017 return ((new Double(value.toString().trim())).doubleValue());
2018 } catch (NumberFormatException ex) {
2019 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.doublefail").toString(),
2020 new Object[] {value.toString().trim(), columnIndex}));
2021 }
2022 }
2023
2024 /**
2025 * Retrieves the value of the designated column in the current row
2026 * of this <code>CachedRowSetImpl</code> object as a
2027 * <code>java.math.BigDecimal</code> object.
2028 * <P>
2029 * This method is deprecated; use the version of <code>getBigDecimal</code>
2030 * that does not take a scale parameter and returns a value with full
2031 * precision.
2032 *
2033 * @param columnIndex the first column is <code>1</code>, the second
2034 * is <code>2</code>, and so on; must be <code>1</code> or larger
2035 * and equal to or less than the number of columns in the rowset
2036 * @param scale the number of digits to the right of the decimal point in the
2037 * value returned
2038 * @return the column value with the specified number of digits to the right
2039 * of the decimal point; if the value is SQL <code>NULL</code>, the
2040 * result is <code>null</code>
2041 * @throws SQLException if the given column index is out of bounds,
2042 * the cursor is not on a valid row, or this method fails
2043 * @deprecated
2044 */
2045 public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
2046 Object value;
2047 BigDecimal bDecimal, retVal;
2048
2049 // sanity check.
2050 checkIndex(columnIndex);
2051 // make sure the cursor is on a valid row
2052 checkCursor();
2053
2054 setLastValueNull(false);
2055 value = getCurrentRow().getColumnObject(columnIndex);
2056
2057 // check for SQL NULL
2058 if (value == null) {
2059 setLastValueNull(true);
2060 return (new BigDecimal(0));
2061 }
2062
2063 bDecimal = this.getBigDecimal(columnIndex);
2064
2065 retVal = bDecimal.setScale(scale);
2066
2067 return retVal;
2068 }
2069
2070 /**
2071 * Retrieves the value of the designated column in the current row
2072 * of this <code>CachedRowSetImpl</code> object as a
2073 * <code>byte</code> array value.
2074 *
2075 * @param columnIndex the first column is <code>1</code>, the second
2076 * is <code>2</code>, and so on; must be <code>1</code> or larger
2077 * and equal to or less than the number of columns in the rowset
2078 * @return the column value as a <code>byte</code> array in the Java programming
2079 * language; if the value is SQL <code>NULL</code>, the
2080 * result is <code>null</code>
2081 *
2082 * @throws SQLException if (1) the given column index is out of bounds,
2083 * (2) the cursor is not on one of this rowset's rows or its
2084 * insert row, or (3) the designated column does not store an
2085 * SQL <code><b>BINARY</b>, <b>VARBINARY</b> or
2086 * LONGVARBINARY</code> value.
2087 * The bold SQL type designates the recommended return type.
2088 * @see #getBytes(String)
2089 */
2090 public byte[] getBytes(int columnIndex) throws SQLException {
2091 // sanity check.
2092 checkIndex(columnIndex);
2093 // make sure the cursor is on a valid row
2094 checkCursor();
2095
2096 if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
2097 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2098 }
2099
2100 return (byte[])(getCurrentRow().getColumnObject(columnIndex));
2101 }
2102
2103 /**
2104 * Retrieves the value of the designated column in the current row
2105 * of this <code>CachedRowSetImpl</code> object as a
2106 * <code>java.sql.Date</code> object.
2107 *
2108 * @param columnIndex the first column is <code>1</code>, the second
2109 * is <code>2</code>, and so on; must be <code>1</code> or larger
2110 * and equal to or less than the number of columns in the rowset
2111 * @return the column value as a <code>java.sql.Data</code> object; if
2112 * the value is SQL <code>NULL</code>, the
2113 * result is <code>null</code>
2114 * @throws SQLException if the given column index is out of bounds,
2115 * the cursor is not on a valid row, or this method fails
2116 */
2117 public java.sql.Date getDate(int columnIndex) throws SQLException {
2118 Object value;
2119
2120 // sanity check.
2121 checkIndex(columnIndex);
2122 // make sure the cursor is on a valid row
2123 checkCursor();
2124
2125 setLastValueNull(false);
2126 value = getCurrentRow().getColumnObject(columnIndex);
2127
2128 // check for SQL NULL
2129 if (value == null) {
2130 setLastValueNull(true);
2131 return null;
2132 }
2133
2134 /*
2135 * The object coming back from the db could be
2136 * a date, a timestamp, or a char field variety.
2137 * If it's a date type return it, a timestamp
2138 * we turn into a long and then into a date,
2139 * char strings we try to parse. Yuck.
2140 */
2141 switch (RowSetMD.getColumnType(columnIndex)) {
2142 case java.sql.Types.DATE: {
2143 long sec = ((java.sql.Date)value).getTime();
2144 return new java.sql.Date(sec);
2145 }
2146 case java.sql.Types.TIMESTAMP: {
2147 long sec = ((java.sql.Timestamp)value).getTime();
2148 return new java.sql.Date(sec);
2149 }
2150 case java.sql.Types.CHAR:
2151 case java.sql.Types.VARCHAR:
2152 case java.sql.Types.LONGVARCHAR: {
2153 try {
2154 DateFormat df = DateFormat.getDateInstance();
2155 return ((java.sql.Date)(df.parse(value.toString())));
2156 } catch (ParseException ex) {
2157 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.datefail").toString(),
2158 new Object[] {value.toString().trim(), columnIndex}));
2159 }
2160 }
2161 default: {
2162 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.datefail").toString(),
2163 new Object[] {value.toString().trim(), columnIndex}));
2164 }
2165 }
2166 }
2167
2168 /**
2169 * Retrieves the value of the designated column in the current row
2170 * of this <code>CachedRowSetImpl</code> object as a
2171 * <code>java.sql.Time</code> object.
2172 *
2173 * @param columnIndex the first column is <code>1</code>, the second
2174 * is <code>2</code>, and so on; must be <code>1</code> or larger
2175 * and equal to or less than the number of columns in the rowset
2176 * @return the column value; if the value is SQL <code>NULL</code>, the
2177 * result is <code>null</code>
2178 * @throws SQLException if the given column index is out of bounds,
2179 * the cursor is not on a valid row, or this method fails
2180 */
2181 public java.sql.Time getTime(int columnIndex) throws SQLException {
2182 Object value;
2183
2184 // sanity check.
2185 checkIndex(columnIndex);
2186 // make sure the cursor is on a valid row
2187 checkCursor();
2188
2189 setLastValueNull(false);
2190 value = getCurrentRow().getColumnObject(columnIndex);
2191
2192 // check for SQL NULL
2193 if (value == null) {
2194 setLastValueNull(true);
2195 return null;
2196 }
2197
2198 /*
2199 * The object coming back from the db could be
2200 * a date, a timestamp, or a char field variety.
2201 * If it's a date type return it, a timestamp
2202 * we turn into a long and then into a date,
2203 * char strings we try to parse. Yuck.
2204 */
2205 switch (RowSetMD.getColumnType(columnIndex)) {
2206 case java.sql.Types.TIME: {
2207 return (java.sql.Time)value;
2208 }
2209 case java.sql.Types.TIMESTAMP: {
2210 long sec = ((java.sql.Timestamp)value).getTime();
2211 return new java.sql.Time(sec);
2212 }
2213 case java.sql.Types.CHAR:
2214 case java.sql.Types.VARCHAR:
2215 case java.sql.Types.LONGVARCHAR: {
2216 try {
2217 DateFormat tf = DateFormat.getTimeInstance();
2218 return ((java.sql.Time)(tf.parse(value.toString())));
2219 } catch (ParseException ex) {
2220 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2221 new Object[] {value.toString().trim(), columnIndex}));
2222 }
2223 }
2224 default: {
2225 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2226 new Object[] {value.toString().trim(), columnIndex}));
2227 }
2228 }
2229 }
2230
2231 /**
2232 * Retrieves the value of the designated column in the current row
2233 * of this <code>CachedRowSetImpl</code> object as a
2234 * <code>java.sql.Timestamp</code> object.
2235 *
2236 * @param columnIndex the first column is <code>1</code>, the second
2237 * is <code>2</code>, and so on; must be <code>1</code> or larger
2238 * and equal to or less than the number of columns in the rowset
2239 * @return the column value; if the value is SQL <code>NULL</code>, the
2240 * result is <code>null</code>
2241 * @throws SQLException if the given column index is out of bounds,
2242 * the cursor is not on a valid row, or this method fails
2243 */
2244 public java.sql.Timestamp getTimestamp(int columnIndex) throws SQLException {
2245 Object value;
2246
2247 // sanity check.
2248 checkIndex(columnIndex);
2249 // make sure the cursor is on a valid row
2250 checkCursor();
2251
2252 setLastValueNull(false);
2253 value = getCurrentRow().getColumnObject(columnIndex);
2254
2255 // check for SQL NULL
2256 if (value == null) {
2257 setLastValueNull(true);
2258 return null;
2259 }
2260
2261 /*
2262 * The object coming back from the db could be
2263 * a date, a timestamp, or a char field variety.
2264 * If it's a date type return it; a timestamp
2265 * we turn into a long and then into a date;
2266 * char strings we try to parse. Yuck.
2267 */
2268 switch (RowSetMD.getColumnType(columnIndex)) {
2269 case java.sql.Types.TIMESTAMP: {
2270 return (java.sql.Timestamp)value;
2271 }
2272 case java.sql.Types.TIME: {
2273 long sec = ((java.sql.Time)value).getTime();
2274 return new java.sql.Timestamp(sec);
2275 }
2276 case java.sql.Types.DATE: {
2277 long sec = ((java.sql.Date)value).getTime();
2278 return new java.sql.Timestamp(sec);
2279 }
2280 case java.sql.Types.CHAR:
2281 case java.sql.Types.VARCHAR:
2282 case java.sql.Types.LONGVARCHAR: {
2283 try {
2284 DateFormat tf = DateFormat.getTimeInstance();
2285 return ((java.sql.Timestamp)(tf.parse(value.toString())));
2286 } catch (ParseException ex) {
2287 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2288 new Object[] {value.toString().trim(), columnIndex}));
2289 }
2290 }
2291 default: {
2292 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.timefail").toString(),
2293 new Object[] {value.toString().trim(), columnIndex}));
2294 }
2295 }
2296 }
2297
2298 /**
2299 * Retrieves the value of the designated column in the current row of this
2300 * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2301 * object.
2302 *
2303 * A column value can be retrieved as a stream of ASCII characters
2304 * and then read in chunks from the stream. This method is particularly
2305 * suitable for retrieving large <code>LONGVARCHAR</code> values. The JDBC
2306 * driver will do any necessary conversion from the database format into ASCII.
2307 *
2308 * <P><B>Note:</B> All the data in the returned stream must be
2309 * read prior to getting the value of any other column. The next
2310 * call to a get method implicitly closes the stream. . Also, a
2311 * stream may return <code>0</code> for <code>CachedRowSetImpl.available()</code>
2312 * whether there is data available or not.
2313 *
2314 * @param columnIndex the first column is <code>1</code>, the second
2315 * is <code>2</code>, and so on; must be <code>1</code> or larger
2316 * and equal to or less than the number of columns in this rowset
2317 * @return a Java input stream that delivers the database column value
2318 * as a stream of one-byte ASCII characters. If the value is SQL
2319 * <code>NULL</code>, the result is <code>null</code>.
2320 * @throws SQLException if (1) the given column index is out of bounds,
2321 * (2) the cursor is not on one of this rowset's rows or its
2322 * insert row, or (3) the designated column does not store an
2323 * SQL <code>CHAR, VARCHAR</code>, <code><b>LONGVARCHAR</b></code>
2324 * <code>BINARY, VARBINARY</code> or <code>LONGVARBINARY</code> value. The
2325 * bold SQL type designates the recommended return types that this method is
2326 * used to retrieve.
2327 * @see #getAsciiStream(String)
2328 */
2329 public java.io.InputStream getAsciiStream(int columnIndex) throws SQLException {
2330 Object value;
2331
2332 // always free an old stream
2333 asciiStream = null;
2334
2335 // sanity check
2336 checkIndex(columnIndex);
2337 //make sure the cursor is on a vlid row
2338 checkCursor();
2339
2340 value = getCurrentRow().getColumnObject(columnIndex);
2341 if (value == null) {
2342 lastValueNull = true;
2343 return null;
2344 }
2345
2346 try {
2347 if (isString(RowSetMD.getColumnType(columnIndex))) {
2348 asciiStream = new ByteArrayInputStream(((String)value).getBytes("ASCII"));
2349 } else {
2350 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2351 }
2352 } catch (java.io.UnsupportedEncodingException ex) {
2353 throw new SQLException(ex.getMessage());
2354 }
2355
2356 return (java.io.InputStream)asciiStream;
2357 }
2358
2359 /**
2360 * A column value can be retrieved as a stream of Unicode characters
2361 * and then read in chunks from the stream. This method is particularly
2362 * suitable for retrieving large LONGVARCHAR values. The JDBC driver will
2363 * do any necessary conversion from the database format into Unicode.
2364 *
2365 * <P><B>Note:</B> All the data in the returned stream must be
2366 * read prior to getting the value of any other column. The next
2367 * call to a get method implicitly closes the stream. . Also, a
2368 * stream may return 0 for available() whether there is data
2369 * available or not.
2370 *
2371 * @param columnIndex the first column is <code>1</code>, the second
2372 * is <code>2</code>, and so on; must be <code>1</code> or larger
2373 * and equal to or less than the number of columns in this rowset
2374 * @return a Java input stream that delivers the database column value
2375 * as a stream of two byte Unicode characters. If the value is SQL NULL
2376 * then the result is null.
2377 * @throws SQLException if an error occurs
2378 * @deprecated
2379 */
2380 public java.io.InputStream getUnicodeStream(int columnIndex) throws SQLException {
2381 // always free an old stream
2382 unicodeStream = null;
2383
2384 // sanity check.
2385 checkIndex(columnIndex);
2386 // make sure the cursor is on a valid row
2387 checkCursor();
2388
2389 if (isBinary(RowSetMD.getColumnType(columnIndex)) == false &&
2390 isString(RowSetMD.getColumnType(columnIndex)) == false) {
2391 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2392 }
2393
2394 Object value = getCurrentRow().getColumnObject(columnIndex);
2395 if (value == null) {
2396 lastValueNull = true;
2397 return null;
2398 }
2399
2400 unicodeStream = new StringBufferInputStream(value.toString());
2401
2402 return (java.io.InputStream)unicodeStream;
2403 }
2404
2405 /**
2406 * Retrieves the value of the designated column in the current row of this
2407 * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2408 * object.
2409 * <P>
2410 * A column value can be retrieved as a stream of uninterpreted bytes
2411 * and then read in chunks from the stream. This method is particularly
2412 * suitable for retrieving large <code>LONGVARBINARY</code> values.
2413 *
2414 * <P><B>Note:</B> All the data in the returned stream must be
2415 * read prior to getting the value of any other column. The next
2416 * call to a get method implicitly closes the stream. Also, a
2417 * stream may return <code>0</code> for
2418 * <code>CachedRowSetImpl.available()</code> whether there is data
2419 * available or not.
2420 *
2421 * @param columnIndex the first column is <code>1</code>, the second
2422 * is <code>2</code>, and so on; must be <code>1</code> or larger
2423 * and equal to or less than the number of columns in the rowset
2424 * @return a Java input stream that delivers the database column value
2425 * as a stream of uninterpreted bytes. If the value is SQL <code>NULL</code>
2426 * then the result is <code>null</code>.
2427 * @throws SQLException if (1) the given column index is out of bounds,
2428 * (2) the cursor is not on one of this rowset's rows or its
2429 * insert row, or (3) the designated column does not store an
2430 * SQL <code>BINARY, VARBINARY</code> or <code><b>LONGVARBINARY</b></code>
2431 * The bold type indicates the SQL type that this method is recommened
2432 * to retrieve.
2433 * @see #getBinaryStream(String)
2434 */
2435 public java.io.InputStream getBinaryStream(int columnIndex) throws SQLException {
2436
2437 // always free an old stream
2438 binaryStream = null;
2439
2440 // sanity check.
2441 checkIndex(columnIndex);
2442 // make sure the cursor is on a valid row
2443 checkCursor();
2444
2445 if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
2446 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
2447 }
2448
2449 Object value = getCurrentRow().getColumnObject(columnIndex);
2450 if (value == null) {
2451 lastValueNull = true;
2452 return null;
2453 }
2454
2455 binaryStream = new ByteArrayInputStream((byte[])value);
2456
2457 return (java.io.InputStream)binaryStream;
2458
2459 }
2460
2461
2462 // Methods for accessing results by column name
2463
2464 /**
2465 * Retrieves the value stored in the designated column
2466 * of the current row as a <code>String</code> object.
2467 *
2468 * @param columnName a <code>String</code> object giving the SQL name of
2469 * a column in this <code>CachedRowSetImpl</code> object
2470 * @return the column value; if the value is SQL <code>NULL</code>,
2471 * the result is <code>null</code>
2472 * @throws SQLException if (1) the given column name is not the name of
2473 * a column in this rowset, (2) the cursor is not on one of
2474 * this rowset's rows or its insert row, or (3) the designated
2475 * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2476 * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, <b>CHAR</b>,
2477 * <b>VARCHAR</b></code> or <code>LONGVARCHAR<</code> value. The bold SQL type
2478 * designates the recommended return type.
2479 */
2480 public String getString(String columnName) throws SQLException {
2481 return getString(getColIdxByName(columnName));
2482 }
2483
2484 /**
2485 * Retrieves the value stored in the designated column
2486 * of the current row as a <code>boolean</code> value.
2487 *
2488 * @param columnName a <code>String</code> object giving the SQL name of
2489 * a column in this <code>CachedRowSetImpl</code> object
2490 * @return the column value as a <code>boolean</code> in the Java programming
2491 * language; if the value is SQL <code>NULL</code>,
2492 * the result is <code>false</code>
2493 * @throws SQLException if (1) the given column name is not the name of
2494 * a column in this rowset, (2) the cursor is not on one of
2495 * this rowset's rows or its insert row, or (3) the designated
2496 * column does not store an SQL <code>BOOLEAN</code> value
2497 * @see #getBoolean(int)
2498 */
2499 public boolean getBoolean(String columnName) throws SQLException {
2500 return getBoolean(getColIdxByName(columnName));
2501 }
2502
2503 /**
2504 * Retrieves the value stored in the designated column
2505 * of the current row as a <code>byte</code> value.
2506 *
2507 * @param columnName a <code>String</code> object giving the SQL name of
2508 * a column in this <code>CachedRowSetImpl</code> object
2509 * @return the column value as a <code>byte</code> in the Java programming
2510 * language; if the value is SQL <code>NULL</code>, the result is <code>0</code>
2511 * @throws SQLException if (1) the given column name is not the name of
2512 * a column in this rowset, (2) the cursor is not on one of
2513 * this rowset's rows or its insert row, or (3) the designated
2514 * column does not store an SQL <code><B>TINYINT</B>, SMALLINT, INTEGER,
2515 * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2516 * VARCHAR</code> or <code>LONGVARCHAR</code> value. The
2517 * bold type designates the recommended return type
2518 */
2519 public byte getByte(String columnName) throws SQLException {
2520 return getByte(getColIdxByName(columnName));
2521 }
2522
2523 /**
2524 * Retrieves the value stored in the designated column
2525 * of the current row as a <code>short</code> value.
2526 *
2527 * @param columnName a <code>String</code> object giving the SQL name of
2528 * a column in this <code>CachedRowSetImpl</code> object
2529 * @return the column value; if the value is SQL <code>NULL</code>,
2530 * the result is <code>0</code>
2531 * @throws SQLException if (1) the given column name is not the name of
2532 * a column in this rowset, (2) the cursor is not on one of
2533 * this rowset's rows or its insert row, or (3) the designated
2534 * column does not store an SQL <code>TINYINT, <b>SMALLINT</b>, INTEGER
2535 * BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2536 * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2537 * designates the recommended return type.
2538 * @see #getShort(int)
2539 */
2540 public short getShort(String columnName) throws SQLException {
2541 return getShort(getColIdxByName(columnName));
2542 }
2543
2544 /**
2545 * Retrieves the value stored in the designated column
2546 * of the current row as an <code>int</code> value.
2547 *
2548 * @param columnName a <code>String</code> object giving the SQL name of
2549 * a column in this <code>CachedRowSetImpl</code> object
2550 * @return the column value; if the value is SQL <code>NULL</code>,
2551 * the result is <code>0</code>
2552 * @throws SQLException if (1) the given column name is not the name
2553 * of a column in this rowset,
2554 * (2) the cursor is not on one of this rowset's rows or its
2555 * insert row, or (3) the designated column does not store an
2556 * SQL <code>TINYINT, SMALLINT, <b>INTEGER</b>, BIGINT, REAL
2557 * FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR</code>
2558 * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
2559 * recommended return type.
2560 */
2561 public int getInt(String columnName) throws SQLException {
2562 return getInt(getColIdxByName(columnName));
2563 }
2564
2565 /**
2566 * Retrieves the value stored in the designated column
2567 * of the current row as a <code>long</code> value.
2568 *
2569 * @param columnName a <code>String</code> object giving the SQL name of
2570 * a column in this <code>CachedRowSetImpl</code> object
2571 * @return the column value; if the value is SQL <code>NULL</code>,
2572 * the result is <code>0</code>
2573 * @throws SQLException if (1) the given column name is not the name of
2574 * a column in this rowset, (2) the cursor is not on one of
2575 * this rowset's rows or its insert row, or (3) the designated
2576 * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2577 * <b>BIGINT</b>, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2578 * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2579 * designates the recommended return type.
2580 * @see #getLong(int)
2581 */
2582 public long getLong(String columnName) throws SQLException {
2583 return getLong(getColIdxByName(columnName));
2584 }
2585
2586 /**
2587 * Retrieves the value stored in the designated column
2588 * of the current row as a <code>float</code> value.
2589 *
2590 * @param columnName a <code>String</code> object giving the SQL name of
2591 * a column in this <code>CachedRowSetImpl</code> object
2592 * @return the column value; if the value is SQL <code>NULL</code>,
2593 * the result is <code>0</code>
2594 * @throws SQLException if (1) the given column name is not the name of
2595 * a column in this rowset, (2) the cursor is not on one of
2596 * this rowset's rows or its insert row, or (3) the designated
2597 * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2598 * BIGINT, <b>REAL</b>, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR,
2599 * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2600 * designates the recommended return type.
2601 * @see #getFloat(String)
2602 */
2603 public float getFloat(String columnName) throws SQLException {
2604 return getFloat(getColIdxByName(columnName));
2605 }
2606
2607 /**
2608 * Retrieves the value stored in the designated column
2609 * of the current row of this <code>CachedRowSetImpl</code> object
2610 * as a <code>double</code> value.
2611 *
2612 * @param columnName a <code>String</code> object giving the SQL name of
2613 * a column in this <code>CachedRowSetImpl</code> object
2614 * @return the column value; if the value is SQL <code>NULL</code>,
2615 * the result is <code>0</code>
2616 * @throws SQLException if (1) the given column name is not the name of
2617 * a column in this rowset, (2) the cursor is not on one of
2618 * this rowset's rows or its insert row, or (3) the designated
2619 * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2620 * BIGINT, REAL, <b>FLOAT</b>, <b>DOUBLE</b>, DECIMAL, NUMERIC, BIT, CHAR,
2621 * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2622 * designates the recommended return types.
2623 * @see #getDouble(int)
2624 */
2625 public double getDouble(String columnName) throws SQLException {
2626 return getDouble(getColIdxByName(columnName));
2627 }
2628
2629 /**
2630 * Retrieves the value stored in the designated column
2631 * of the current row as a <code>java.math.BigDecimal</code> object.
2632 *
2633 * @param columnName a <code>String</code> object giving the SQL name of
2634 * a column in this <code>CachedRowSetImpl</code> object
2635 * @param scale the number of digits to the right of the decimal point
2636 * @return a java.math.BugDecimal object with <code><i>scale</i></code>
2637 * number of digits to the right of the decimal point.
2638 * @throws SQLException if (1) the given column name is not the name of
2639 * a column in this rowset, (2) the cursor is not on one of
2640 * this rowset's rows or its insert row, or (3) the designated
2641 * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
2642 * BIGINT, REAL, FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT CHAR,
2643 * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
2644 * designates the recommended return type that this method is used to
2645 * retrieve.
2646 * @deprecated Use the <code>getBigDecimal(String columnName)</code>
2647 * method instead
2648 */
2649 public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException {
2650 return getBigDecimal(getColIdxByName(columnName), scale);
2651 }
2652
2653 /**
2654 * Retrieves the value stored in the designated column
2655 * of the current row as a <code>byte</code> array.
2656 * The bytes represent the raw values returned by the driver.
2657 *
2658 * @param columnName a <code>String</code> object giving the SQL name of
2659 * a column in this <code>CachedRowSetImpl</code> object
2660 * @return the column value as a <code>byte</code> array in the Java programming
2661 * language; if the value is SQL <code>NULL</code>, the result is <code>null</code>
2662 * @throws SQLException if (1) the given column name is not the name of
2663 * a column in this rowset, (2) the cursor is not on one of
2664 * this rowset's rows or its insert row, or (3) the designated
2665 * column does not store an SQL <code><b>BINARY</b>, <b>VARBINARY</b>
2666 * </code> or <code>LONGVARBINARY</code> values
2667 * The bold SQL type designates the recommended return type.
2668 * @see #getBytes(int)
2669 */
2670 public byte[] getBytes(String columnName) throws SQLException {
2671 return getBytes(getColIdxByName(columnName));
2672 }
2673
2674 /**
2675 * Retrieves the value stored in the designated column
2676 * of the current row as a <code>java.sql.Date</code> object.
2677 *
2678 * @param columnName a <code>String</code> object giving the SQL name of
2679 * a column in this <code>CachedRowSetImpl</code> object
2680 * @return the column value; if the value is SQL <code>NULL</code>,
2681 * the result is <code>null</code>
2682 * @throws SQLException if (1) the given column name is not the name of
2683 * a column in this rowset, (2) the cursor is not on one of
2684 * this rowset's rows or its insert row, or (3) the designated
2685 * column does not store an SQL <code>DATE</code> or
2686 * <code>TIMESTAMP</code> value
2687 */
2688 public java.sql.Date getDate(String columnName) throws SQLException {
2689 return getDate(getColIdxByName(columnName));
2690 }
2691
2692 /**
2693 * Retrieves the value stored in the designated column
2694 * of the current row as a <code>java.sql.Time</code> object.
2695 *
2696 * @param columnName a <code>String</code> object giving the SQL name of
2697 * a column in this <code>CachedRowSetImpl</code> object
2698 * @return the column value; if the value is SQL <code>NULL</code>,
2699 * the result is <code>null</code>
2700 * @throws SQLException if the given column name does not match one of
2701 * this rowset's column names or the cursor is not on one of
2702 * this rowset's rows or its insert row
2703 */
2704 public java.sql.Time getTime(String columnName) throws SQLException {
2705 return getTime(getColIdxByName(columnName));
2706 }
2707
2708 /**
2709 * Retrieves the value stored in the designated column
2710 * of the current row as a <code>java.sql.Timestamp</code> object.
2711 *
2712 * @param columnName a <code>String</code> object giving the SQL name of
2713 * a column in this <code>CachedRowSetImpl</code> object
2714 * @return the column value; if the value is SQL <code>NULL</code>,
2715 * the result is <code>null</code>
2716 * @throws SQLException if the given column name does not match one of
2717 * this rowset's column names or the cursor is not on one of
2718 * this rowset's rows or its insert row
2719 */
2720 public java.sql.Timestamp getTimestamp(String columnName) throws SQLException {
2721 return getTimestamp(getColIdxByName(columnName));
2722 }
2723
2724 /**
2725 * Retrieves the value of the designated column in the current row of this
2726 * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2727 * object.
2728 *
2729 * A column value can be retrieved as a stream of ASCII characters
2730 * and then read in chunks from the stream. This method is particularly
2731 * suitable for retrieving large <code>LONGVARCHAR</code> values. The
2732 * <code>SyncProvider</code> will rely on the JDBC driver to do any necessary
2733 * conversion from the database format into ASCII format.
2734 *
2735 * <P><B>Note:</B> All the data in the returned stream must
2736 * be read prior to getting the value of any other column. The
2737 * next call to a <code>getXXX</code> method implicitly closes the stream.
2738 *
2739 * @param columnName a <code>String</code> object giving the SQL name of
2740 * a column in this <code>CachedRowSetImpl</code> object
2741 * @return a Java input stream that delivers the database column value
2742 * as a stream of one-byte ASCII characters. If the value is SQL
2743 * <code>NULL</code>, the result is <code>null</code>.
2744 * @throws SQLException if (1) the given column name is not the name of
2745 * a column in this rowset
2746 * (2) the cursor is not on one of this rowset's rows or its
2747 * insert row, or (3) the designated column does not store an
2748 * SQL <code>CHAR, VARCHAR</code>, <code><b>LONGVARCHAR</b></code>
2749 * <code>BINARY, VARBINARY</code> or <code>LONGVARBINARY</code> value. The
2750 * bold SQL type designates the recommended return types that this method is
2751 * used to retrieve.
2752 * @see #getAsciiStream(int)
2753 */
2754 public java.io.InputStream getAsciiStream(String columnName) throws SQLException {
2755 return getAsciiStream(getColIdxByName(columnName));
2756
2757 }
2758
2759 /**
2760 * A column value can be retrieved as a stream of Unicode characters
2761 * and then read in chunks from the stream. This method is particularly
2762 * suitable for retrieving large <code>LONGVARCHAR</code> values.
2763 * The JDBC driver will do any necessary conversion from the database
2764 * format into Unicode.
2765 *
2766 * <P><B>Note:</B> All the data in the returned stream must
2767 * be read prior to getting the value of any other column. The
2768 * next call to a <code>getXXX</code> method implicitly closes the stream.
2769 *
2770 * @param columnName a <code>String</code> object giving the SQL name of
2771 * a column in this <code>CachedRowSetImpl</code> object
2772 * @return a Java input stream that delivers the database column value
2773 * as a stream of two-byte Unicode characters. If the value is
2774 * SQL <code>NULL</code>, the result is <code>null</code>.
2775 * @throws SQLException if the given column name does not match one of
2776 * this rowset's column names or the cursor is not on one of
2777 * this rowset's rows or its insert row
2778 * @deprecated use the method <code>getCharacterStream</code> instead
2779 */
2780 public java.io.InputStream getUnicodeStream(String columnName) throws SQLException {
2781 return getUnicodeStream(getColIdxByName(columnName));
2782 }
2783
2784 /**
2785 * Retrieves the value of the designated column in the current row of this
2786 * <code>CachedRowSetImpl</code> object as a <code>java.io.InputStream</code>
2787 * object.
2788 * <P>
2789 * A column value can be retrieved as a stream of uninterpreted bytes
2790 * and then read in chunks from the stream. This method is particularly
2791 * suitable for retrieving large <code>LONGVARBINARY</code> values.
2792 *
2793 * <P><B>Note:</B> All the data in the returned stream must be
2794 * read prior to getting the value of any other column. The next
2795 * call to a get method implicitly closes the stream. Also, a
2796 * stream may return <code>0</code> for <code>CachedRowSetImpl.available()</code>
2797 * whether there is data available or not.
2798 *
2799 * @param columnName a <code>String</code> object giving the SQL name of
2800 * a column in this <code>CachedRowSetImpl</code> object
2801 * @return a Java input stream that delivers the database column value
2802 * as a stream of uninterpreted bytes. If the value is SQL
2803 * <code>NULL</code>, the result is <code>null</code>.
2804 * @throws SQLException if (1) the given column name is unknown,
2805 * (2) the cursor is not on one of this rowset's rows or its
2806 * insert row, or (3) the designated column does not store an
2807 * SQL <code>BINARY, VARBINARY</code> or <code><b>LONGVARBINARY</b></code>
2808 * The bold type indicates the SQL type that this method is recommened
2809 * to retrieve.
2810 * @see #getBinaryStream(int)
2811 *
2812 */
2813 public java.io.InputStream getBinaryStream(String columnName) throws SQLException {
2814 return getBinaryStream(getColIdxByName(columnName));
2815 }
2816
2817
2818 // Advanced features:
2819
2820 /**
2821 * The first warning reported by calls on this <code>CachedRowSetImpl</code>
2822 * object is returned. Subsequent <code>CachedRowSetImpl</code> warnings will
2823 * be chained to this <code>SQLWarning</code>.
2824 *
2825 * <P>The warning chain is automatically cleared each time a new
2826 * row is read.
2827 *
2828 * <P><B>Note:</B> This warning chain only covers warnings caused
2829 * by <code>ResultSet</code> methods. Any warning caused by statement
2830 * methods (such as reading OUT parameters) will be chained on the
2831 * <code>Statement</code> object.
2832 *
2833 * @return the first SQLWarning or null
2834 */
2835 public SQLWarning getWarnings() {
2836 return sqlwarn;
2837 }
2838
2839 /**
2840 * Clears all the warnings reporeted for the <code>CachedRowSetImpl</code>
2841 * object. After a call to this method, the <code>getWarnings</code> method
2842 * returns <code>null</code> until a new warning is reported for this
2843 * <code>CachedRowSetImpl</code> object.
2844 */
2845 public void clearWarnings() {
2846 sqlwarn = null;
2847 }
2848
2849 /**
2850 * Retrieves the name of the SQL cursor used by this
2851 * <code>CachedRowSetImpl</code> object.
2852 *
2853 * <P>In SQL, a result table is retrieved through a cursor that is
2854 * named. The current row of a <code>ResultSet</code> can be updated or deleted
2855 * using a positioned update/delete statement that references the
2856 * cursor name. To ensure that the cursor has the proper isolation
2857 * level to support an update operation, the cursor's <code>SELECT</code>
2858 * statement should be of the form <code>select for update</code>.
2859 * If the <code>for update</code> clause
2860 * is omitted, positioned updates may fail.
2861 *
2862 * <P>JDBC supports this SQL feature by providing the name of the
2863 * SQL cursor used by a <code>ResultSet</code> object. The current row
2864 * of a result set is also the current row of this SQL cursor.
2865 *
2866 * <P><B>Note:</B> If positioned updates are not supported, an
2867 * <code>SQLException</code> is thrown.
2868 *
2869 * @return the SQL cursor name for this <code>CachedRowSetImpl</code> object's
2870 * cursor
2871 * @throws SQLException if an error occurs
2872 */
2873 public String getCursorName() throws SQLException {
2874 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.posupdate").toString());
2875 }
2876
2877 /**
2878 * Retrieves a <code>ResultSetMetaData</code> object instance that
2879 * contains information about the <code>CachedRowSet</code> object.
2880 * However, applications should cast the returned object to a
2881 * <code>RowSetMetaData</code> interface implementation. In the
2882 * reference implementation, this cast can be done on the
2883 * <code>RowSetMetaDataImpl</code> class.
2884 * <P>
2885 * For example:
2886 * <pre>
2887 * CachedRowSet crs = new CachedRowSetImpl();
2888 * RowSetMetaDataImpl metaData =
2889 * (RowSetMetaDataImpl)crs.getMetaData();
2890 * // Set the number of columns in the RowSet object for
2891 * // which this RowSetMetaDataImpl object was created to the
2892 * // given number.
2893 * metaData.setColumnCount(3);
2894 * crs.setMetaData(metaData);
2895 * </pre>
2896 *
2897 * @return the <code>ResultSetMetaData</code> object that describes this
2898 * <code>CachedRowSetImpl</code> object's columns
2899 * @throws SQLException if an error occurs in generating the RowSet
2900 * meta data; or if the <code>CachedRowSetImpl</code> is empty.
2901 * @see javax.sql.RowSetMetaData
2902 */
2903 public ResultSetMetaData getMetaData() throws SQLException {
2904 return (ResultSetMetaData)RowSetMD;
2905 }
2906
2907
2908 /**
2909 * Retrieves the value of the designated column in the current row
2910 * of this <code>CachedRowSetImpl</code> object as an
2911 * <code>Object</code> value.
2912 * <P>
2913 * The type of the <code>Object</code> will be the default
2914 * Java object type corresponding to the column's SQL type,
2915 * following the mapping for built-in types specified in the JDBC 3.0
2916 * specification.
2917 * <P>
2918 * This method may also be used to read datatabase-specific
2919 * abstract data types.
2920 * <P>
2921 * This implementation of the method <code>getObject</code> extends its
2922 * behavior so that it gets the attributes of an SQL structured type
2923 * as an array of <code>Object</code> values. This method also custom
2924 * maps SQL user-defined types to classes in the Java programming language.
2925 * When the specified column contains
2926 * a structured or distinct value, the behavior of this method is as
2927 * if it were a call to the method <code>getObject(columnIndex,
2928 * this.getStatement().getConnection().getTypeMap())</code>.
2929 *
2930 * @param columnIndex the first column is <code>1</code>, the second
2931 * is <code>2</code>, and so on; must be <code>1</code> or larger
2932 * and equal to or less than the number of columns in the rowset
2933 * @return a <code>java.lang.Object</code> holding the column value;
2934 * if the value is SQL <code>NULL</code>, the result is <code>null</code>
2935 * @throws SQLException if the given column index is out of bounds,
2936 * the cursor is not on a valid row, or there is a problem getting
2937 * the <code>Class</code> object for a custom mapping
2938 * @see #getObject(String)
2939 */
2940 public Object getObject(int columnIndex) throws SQLException {
2941 Object value;
2942 Map<String, Class<?>> map;
2943
2944 // sanity check.
2945 checkIndex(columnIndex);
2946 // make sure the cursor is on a valid row
2947 checkCursor();
2948
2949 setLastValueNull(false);
2950 value = getCurrentRow().getColumnObject(columnIndex);
2951
2952 // check for SQL NULL
2953 if (value == null) {
2954 setLastValueNull(true);
2955 return null;
2956 }
2957 if (value instanceof Struct) {
2958 Struct s = (Struct)value;
2959 map = getTypeMap();
2960 // look up the class in the map
2961 Class c = (Class)map.get(s.getSQLTypeName());
2962 if (c != null) {
2963 // create new instance of the class
2964 SQLData obj = null;
2965 try {
2966 obj = (SQLData)c.newInstance();
2967 } catch (java.lang.InstantiationException ex) {
2968 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
2969 ex.getMessage()));
2970 } catch (java.lang.IllegalAccessException ex) {
2971 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
2972 ex.getMessage()));
2973 }
2974 // get the attributes from the struct
2975 Object attribs[] = s.getAttributes(map);
2976 // create the SQLInput "stream"
2977 SQLInputImpl sqlInput = new SQLInputImpl(attribs, map);
2978 // read the values...
2979 obj.readSQL(sqlInput, s.getSQLTypeName());
2980 return (Object)obj;
2981 }
2982 }
2983 return value;
2984 }
2985
2986 /**
2987 * Retrieves the value of the designated column in the current row
2988 * of this <code>CachedRowSetImpl</code> object as an
2989 * <code>Object</code> value.
2990 * <P>
2991 * The type of the <code>Object</code> will be the default
2992 * Java object type corresponding to the column's SQL type,
2993 * following the mapping for built-in types specified in the JDBC 3.0
2994 * specification.
2995 * <P>
2996 * This method may also be used to read datatabase-specific
2997 * abstract data types.
2998 * <P>
2999 * This implementation of the method <code>getObject</code> extends its
3000 * behavior so that it gets the attributes of an SQL structured type
3001 * as an array of <code>Object</code> values. This method also custom
3002 * maps SQL user-defined types to classes
3003 * in the Java programming language. When the specified column contains
3004 * a structured or distinct value, the behavior of this method is as
3005 * if it were a call to the method <code>getObject(columnIndex,
3006 * this.getStatement().getConnection().getTypeMap())</code>.
3007 *
3008 * @param columnName a <code>String</code> object that must match the
3009 * SQL name of a column in this rowset, ignoring case
3010 * @return a <code>java.lang.Object</code> holding the column value;
3011 * if the value is SQL <code>NULL</code>, the result is <code>null</code>
3012 * @throws SQLException if (1) the given column name does not match one of
3013 * this rowset's column names, (2) the cursor is not
3014 * on a valid row, or (3) there is a problem getting
3015 * the <code>Class</code> object for a custom mapping
3016 * @see #getObject(int)
3017 */
3018 public Object getObject(String columnName) throws SQLException {
3019 return getObject(getColIdxByName(columnName));
3020 }
3021
3022 //----------------------------------------------------------------
3023
3024 /**
3025 * Maps the given column name for one of this <code>CachedRowSetImpl</code>
3026 * object's columns to its column number.
3027 *
3028 * @param columnName a <code>String</code> object that must match the
3029 * SQL name of a column in this rowset, ignoring case
3030 * @return the column index of the given column name
3031 * @throws SQLException if the given column name does not match one
3032 * of this rowset's column names
3033 */
3034 public int findColumn(String columnName) throws SQLException {
3035 return getColIdxByName(columnName);
3036 }
3037
3038
3039 //--------------------------JDBC 2.0-----------------------------------
3040
3041 //---------------------------------------------------------------------
3042 // Getter's and Setter's
3043 //---------------------------------------------------------------------
3044
3045 /**
3046 * Retrieves the value stored in the designated column
3047 * of the current row as a <code>java.io.Reader</code> object.
3048 *
3049 * <P><B>Note:</B> All the data in the returned stream must
3050 * be read prior to getting the value of any other column. The
3051 * next call to a <code>getXXX</code> method implicitly closes the stream.
3052 *
3053 * @param columnIndex the first column is <code>1</code>, the second
3054 * is <code>2</code>, and so on; must be <code>1</code> or larger
3055 * and equal to or less than the number of columns in the rowset
3056 * @return a Java character stream that delivers the database column value
3057 * as a stream of two-byte unicode characters in a
3058 * <code>java.io.Reader</code> object. If the value is
3059 * SQL <code>NULL</code>, the result is <code>null</code>.
3060 * @throws SQLException if (1) the given column index is out of bounds,
3061 * (2) the cursor is not on one of this rowset's rows or its
3062 * insert row, or (3) the designated column does not store an
3063 * SQL <code>CHAR, VARCHAR, <b>LONGVARCHAR</b>, BINARY, VARBINARY</code> or
3064 * <code>LONGVARBINARY</code> value.
3065 * The bold SQL type designates the recommended return type.
3066 * @see #getCharacterStream(String)
3067 */
3068 public java.io.Reader getCharacterStream(int columnIndex) throws SQLException{
3069
3070 // sanity check.
3071 checkIndex(columnIndex);
3072 // make sure the cursor is on a valid row
3073 checkCursor();
3074
3075 if (isBinary(RowSetMD.getColumnType(columnIndex))) {
3076 Object value = getCurrentRow().getColumnObject(columnIndex);
3077 if (value == null) {
3078 lastValueNull = true;
3079 return null;
3080 }
3081 charStream = new InputStreamReader
3082 (new ByteArrayInputStream((byte[])value));
3083 } else if (isString(RowSetMD.getColumnType(columnIndex))) {
3084 Object value = getCurrentRow().getColumnObject(columnIndex);
3085 if (value == null) {
3086 lastValueNull = true;
3087 return null;
3088 }
3089 charStream = new StringReader(value.toString());
3090 } else {
3091 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
3092 }
3093
3094 return (java.io.Reader)charStream;
3095 }
3096
3097 /**
3098 * Retrieves the value stored in the designated column
3099 * of the current row as a <code>java.io.Reader</code> object.
3100 *
3101 * <P><B>Note:</B> All the data in the returned stream must
3102 * be read prior to getting the value of any other column. The
3103 * next call to a <code>getXXX</code> method implicitly closes the stream.
3104 *
3105 * @param columnName a <code>String</code> object giving the SQL name of
3106 * a column in this <code>CachedRowSetImpl</code> object
3107 * @return a Java input stream that delivers the database column value
3108 * as a stream of two-byte Unicode characters. If the value is
3109 * SQL <code>NULL</code>, the result is <code>null</code>.
3110 * @throws SQLException if (1) the given column name is not the name of
3111 * a column in this rowset, (2) the cursor is not on one of
3112 * this rowset's rows or its insert row, or (3) the designated
3113 * column does not store an SQL <code>CHAR, VARCHAR, <b>LONGVARCHAR</b>,
3114 * BINARY, VARYBINARY</code> or <code>LONGVARBINARY</code> value.
3115 * The bold SQL type designates the recommended return type.
3116 */
3117 public java.io.Reader getCharacterStream(String columnName) throws SQLException {
3118 return getCharacterStream(getColIdxByName(columnName));
3119 }
3120
3121 /**
3122 * Retrieves the value of the designated column in the current row
3123 * of this <code>CachedRowSetImpl</code> object as a
3124 * <code>java.math.BigDecimal</code> object.
3125 *
3126 * @param columnIndex the first column is <code>1</code>, the second
3127 * is <code>2</code>, and so on; must be <code>1</code> or larger
3128 * and equal to or less than the number of columns in the rowset
3129 * @return a <code>java.math.BigDecimal</code> value with full precision;
3130 * if the value is SQL <code>NULL</code>, the result is <code>null</code>
3131 * @throws SQLException if (1) the given column index is out of bounds,
3132 * (2) the cursor is not on one of this rowset's rows or its
3133 * insert row, or (3) the designated column does not store an
3134 * SQL <code>TINYINT, SMALLINT, INTEGER, BIGINT, REAL,
3135 * FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT, CHAR, VARCHAR</code>
3136 * or <code>LONGVARCHAR</code> value. The bold SQL type designates the
3137 * recommended return types that this method is used to retrieve.
3138 * @see #getBigDecimal(String)
3139 */
3140 public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
3141 Object value;
3142
3143 // sanity check.
3144 checkIndex(columnIndex);
3145 // make sure the cursor is on a valid row
3146 checkCursor();
3147
3148 setLastValueNull(false);
3149 value = getCurrentRow().getColumnObject(columnIndex);
3150
3151 // check for SQL NULL
3152 if (value == null) {
3153 setLastValueNull(true);
3154 return null;
3155 }
3156 try {
3157 return (new BigDecimal(value.toString().trim()));
3158 } catch (NumberFormatException ex) {
3159 throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.doublefail").toString(),
3160 new Object[] {value.toString().trim(), columnIndex}));
3161 }
3162 }
3163
3164 /**
3165 * Retrieves the value of the designated column in the current row
3166 * of this <code>CachedRowSetImpl</code> object as a
3167 * <code>java.math.BigDecimal</code> object.
3168 *
3169 * @param columnName a <code>String</code> object that must match the
3170 * SQL name of a column in this rowset, ignoring case
3171 * @return a <code>java.math.BigDecimal</code> value with full precision;
3172 * if the value is SQL <code>NULL</code>, the result is <code>null</code>
3173 * @throws SQLException if (1) the given column name is not the name of
3174 * a column in this rowset, (2) the cursor is not on one of
3175 * this rowset's rows or its insert row, or (3) the designated
3176 * column does not store an SQL <code>TINYINT, SMALLINT, INTEGER
3177 * BIGINT, REAL, FLOAT, DOUBLE, <b>DECIMAL</b>, <b>NUMERIC</b>, BIT CHAR,
3178 * VARCHAR</code> or <code>LONGVARCHAR</code> value. The bold SQL type
3179 * designates the recommended return type that this method is used to
3180 * retrieve
3181 * @see #getBigDecimal(int)
3182 */
3183 public BigDecimal getBigDecimal(String columnName) throws SQLException {
3184 return getBigDecimal(getColIdxByName(columnName));
3185 }
3186
3187 //---------------------------------------------------------------------
3188 // Traversal/Positioning
3189 //---------------------------------------------------------------------
3190
3191 /**
3192 * Returns the number of rows in this <code>CachedRowSetImpl</code> object.
3193 *
3194 * @return number of rows in the rowset
3195 */
3196 public int size() {
3197 return numRows;
3198 }
3199
3200 /**
3201 * Indicates whether the cursor is before the first row in this
3202 * <code>CachedRowSetImpl</code> object.
3203 *
3204 * @return <code>true</code> if the cursor is before the first row;
3205 * <code>false</code> otherwise or if the rowset contains no rows
3206 * @throws SQLException if an error occurs
3207 */
3208 public boolean isBeforeFirst() throws SQLException {
3209 if (cursorPos == 0 && numRows > 0) {
3210 return true;
3211 } else {
3212 return false;
3213 }
3214 }
3215
3216 /**
3217 * Indicates whether the cursor is after the last row in this
3218 * <code>CachedRowSetImpl</code> object.
3219 *
3220 * @return <code>true</code> if the cursor is after the last row;
3221 * <code>false</code> otherwise or if the rowset contains no rows
3222 * @throws SQLException if an error occurs
3223 */
3224 public boolean isAfterLast() throws SQLException {
3225 if (cursorPos == numRows+1 && numRows > 0) {
3226 return true;
3227 } else {
3228 return false;
3229 }
3230 }
3231
3232 /**
3233 * Indicates whether the cursor is on the first row in this
3234 * <code>CachedRowSetImpl</code> object.
3235 *
3236 * @return <code>true</code> if the cursor is on the first row;
3237 * <code>false</code> otherwise or if the rowset contains no rows
3238 * @throws SQLException if an error occurs
3239 */
3240 public boolean isFirst() throws SQLException {
3241 // this becomes nasty because of deletes.
3242 int saveCursorPos = cursorPos;
3243 int saveAbsoluteCursorPos = absolutePos;
3244 internalFirst();
3245 if (cursorPos == saveCursorPos) {
3246 return true;
3247 } else {
3248 cursorPos = saveCursorPos;
3249 absolutePos = saveAbsoluteCursorPos;
3250 return false;
3251 }
3252 }
3253
3254 /**
3255 * Indicates whether the cursor is on the last row in this
3256 * <code>CachedRowSetImpl</code> object.
3257 * <P>
3258 * Note: Calling the method <code>isLast</code> may be expensive
3259 * because the JDBC driver might need to fetch ahead one row in order
3260 * to determine whether the current row is the last row in this rowset.
3261 *
3262 * @return <code>true</code> if the cursor is on the last row;
3263 * <code>false</code> otherwise or if this rowset contains no rows
3264 * @throws SQLException if an error occurs
3265 */
3266 public boolean isLast() throws SQLException {
3267 int saveCursorPos = cursorPos;
3268 int saveAbsoluteCursorPos = absolutePos;
3269 boolean saveShowDeleted = getShowDeleted();
3270 setShowDeleted(true);
3271 internalLast();
3272 if (cursorPos == saveCursorPos) {
3273 setShowDeleted(saveShowDeleted);
3274 return true;
3275 } else {
3276 setShowDeleted(saveShowDeleted);
3277 cursorPos = saveCursorPos;
3278 absolutePos = saveAbsoluteCursorPos;
3279 return false;
3280 }
3281 }
3282
3283 /**
3284 * Moves this <code>CachedRowSetImpl</code> object's cursor to the front of
3285 * the rowset, just before the first row. This method has no effect if
3286 * this rowset contains no rows.
3287 *
3288 * @throws SQLException if an error occurs or the type of this rowset
3289 * is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3290 */
3291 public void beforeFirst() throws SQLException {
3292 if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3293 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.beforefirst").toString());
3294 }
3295 cursorPos = 0;
3296 absolutePos = 0;
3297 notifyCursorMoved();
3298 }
3299
3300 /**
3301 * Moves this <code>CachedRowSetImpl</code> object's cursor to the end of
3302 * the rowset, just after the last row. This method has no effect if
3303 * this rowset contains no rows.
3304 *
3305 * @throws SQLException if an error occurs
3306 */
3307 public void afterLast() throws SQLException {
3308 if (numRows > 0) {
3309 cursorPos = numRows + 1;
3310 absolutePos = 0;
3311 notifyCursorMoved();
3312 }
3313 }
3314
3315 /**
3316 * Moves this <code>CachedRowSetImpl</code> object's cursor to the first row
3317 * and returns <code>true</code> if the operation was successful. This
3318 * method also notifies registered listeners that the cursor has moved.
3319 *
3320 * @return <code>true</code> if the cursor is on a valid row;
3321 * <code>false</code> otherwise or if there are no rows in this
3322 * <code>CachedRowSetImpl</code> object
3323 * @throws SQLException if the type of this rowset
3324 * is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3325 */
3326 public boolean first() throws SQLException {
3327 if(getType() == ResultSet.TYPE_FORWARD_ONLY) {
3328 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.first").toString());
3329 }
3330
3331 // move and notify
3332 boolean ret = this.internalFirst();
3333 notifyCursorMoved();
3334
3335 return ret;
3336 }
3337
3338 /**
3339 * Moves this <code>CachedRowSetImpl</code> object's cursor to the first
3340 * row and returns <code>true</code> if the operation is successful.
3341 * <P>
3342 * This method is called internally by the methods <code>first</code>,
3343 * <code>isFirst</code>, and <code>absolute</code>.
3344 * It in turn calls the method <code>internalNext</code> in order to
3345 * handle the case where the first row is a deleted row that is not visible.
3346 * <p>
3347 * This is a implementation only method and is not required as a standard
3348 * implementation of the <code>CachedRowSet</code> interface.
3349 *
3350 * @return <code>true</code> if the cursor moved to the first row;
3351 * <code>false</code> otherwise
3352 * @throws SQLException if an error occurs
3353 */
3354 protected boolean internalFirst() throws SQLException {
3355 boolean ret = false;
3356
3357 if (numRows > 0) {
3358 cursorPos = 1;
3359 if ((getShowDeleted() == false) && (rowDeleted() == true)) {
3360 ret = internalNext();
3361 } else {
3362 ret = true;
3363 }
3364 }
3365
3366 if (ret == true)
3367 absolutePos = 1;
3368 else
3369 absolutePos = 0;
3370
3371 return ret;
3372 }
3373
3374 /**
3375 * Moves this <code>CachedRowSetImpl</code> object's cursor to the last row
3376 * and returns <code>true</code> if the operation was successful. This
3377 * method also notifies registered listeners that the cursor has moved.
3378 *
3379 * @return <code>true</code> if the cursor is on a valid row;
3380 * <code>false</code> otherwise or if there are no rows in this
3381 * <code>CachedRowSetImpl</code> object
3382 * @throws SQLException if the type of this rowset
3383 * is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3384 */
3385 public boolean last() throws SQLException {
3386 if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3387 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.last").toString());
3388 }
3389
3390 // move and notify
3391 boolean ret = this.internalLast();
3392 notifyCursorMoved();
3393
3394 return ret;
3395 }
3396
3397 /**
3398 * Moves this <code>CachedRowSetImpl</code> object's cursor to the last
3399 * row and returns <code>true</code> if the operation is successful.
3400 * <P>
3401 * This method is called internally by the method <code>last</code>
3402 * when rows have been deleted and the deletions are not visible.
3403 * The method <code>internalLast</code> handles the case where the
3404 * last row is a deleted row that is not visible by in turn calling
3405 * the method <code>internalPrevious</code>.
3406 * <p>
3407 * This is a implementation only method and is not required as a standard
3408 * implementation of the <code>CachedRowSet</code> interface.
3409 *
3410 * @return <code>true</code> if the cursor moved to the last row;
3411 * <code>false</code> otherwise
3412 * @throws SQLException if an error occurs
3413 */
3414 protected boolean internalLast() throws SQLException {
3415 boolean ret = false;
3416
3417 if (numRows > 0) {
3418 cursorPos = numRows;
3419 if ((getShowDeleted() == false) && (rowDeleted() == true)) {
3420 ret = internalPrevious();
3421 } else {
3422 ret = true;
3423 }
3424 }
3425 if (ret == true)
3426 absolutePos = numRows - numDeleted;
3427 else
3428 absolutePos = 0;
3429 return ret;
3430 }
3431
3432 /**
3433 * Returns the number of the current row in this <code>CachedRowSetImpl</code>
3434 * object. The first row is number 1, the second number 2, and so on.
3435 *
3436 * @return the number of the current row; <code>0</code> if there is no
3437 * current row
3438 * @throws SQLException if an error occurs; or if the <code>CacheRowSetImpl</code>
3439 * is empty
3440 */
3441 public int getRow() throws SQLException {
3442 // are we on a valid row? Valid rows are between first and last
3443 if (numRows > 0 &&
3444 cursorPos > 0 &&
3445 cursorPos < (numRows + 1) &&
3446 (getShowDeleted() == false && rowDeleted() == false)) {
3447 return absolutePos;
3448 } else if (getShowDeleted() == true) {
3449 return cursorPos;
3450 } else {
3451 return 0;
3452 }
3453 }
3454
3455 /**
3456 * Moves this <code>CachedRowSetImpl</code> object's cursor to the row number
3457 * specified.
3458 *
3459 * <p>If the number is positive, the cursor moves to an absolute row with
3460 * respect to the beginning of the rowset. The first row is row 1, the second
3461 * is row 2, and so on. For example, the following command, in which
3462 * <code>crs</code> is a <code>CachedRowSetImpl</code> object, moves the cursor
3463 * to the fourth row, starting from the beginning of the rowset.
3464 * <PRE><code>
3465 *
3466 * crs.absolute(4);
3467 *
3468 * </code> </PRE>
3469 * <P>
3470 * If the number is negative, the cursor moves to an absolute row position
3471 * with respect to the end of the rowset. For example, calling
3472 * <code>absolute(-1)</code> positions the cursor on the last row,
3473 * <code>absolute(-2)</code> moves it on the next-to-last row, and so on.
3474 * If the <code>CachedRowSetImpl</code> object <code>crs</code> has five rows,
3475 * the following command moves the cursor to the fourth-to-last row, which
3476 * in the case of a rowset with five rows, is also the second row, counting
3477 * from the beginning.
3478 * <PRE><code>
3479 *
3480 * crs.absolute(-4);
3481 *
3482 * </code> </PRE>
3483 *
3484 * If the number specified is larger than the number of rows, the cursor
3485 * will move to the position after the last row. If the number specified
3486 * would move the cursor one or more rows before the first row, the cursor
3487 * moves to the position before the first row.
3488 * <P>
3489 * Note: Calling <code>absolute(1)</code> is the same as calling the
3490 * method <code>first()</code>. Calling <code>absolute(-1)</code> is the
3491 * same as calling <code>last()</code>.
3492 *
3493 * @param row a positive number to indicate the row, starting row numbering from
3494 * the first row, which is <code>1</code>; a negative number to indicate
3495 * the row, starting row numbering from the last row, which is
3496 * <code>-1</code>; it must not be <code>0</code>
3497 * @return <code>true</code> if the cursor is on the rowset; <code>false</code>
3498 * otherwise
3499 * @throws SQLException if the given cursor position is <code>0</code> or the
3500 * type of this rowset is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3501 */
3502 public boolean absolute( int row ) throws SQLException {
3503 if (row == 0 || getType() == ResultSet.TYPE_FORWARD_ONLY) {
3504 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.absolute").toString());
3505 }
3506
3507 if (row > 0) { // we are moving foward
3508 if (row > numRows) {
3509 // fell off the end
3510 afterLast();
3511 return false;
3512 } else {
3513 if (absolutePos <= 0)
3514 internalFirst();
3515 }
3516 } else { // we are moving backward
3517 if (cursorPos + row < 0) {
3518 // fell off the front
3519 beforeFirst();
3520 return false;
3521 } else {
3522 if (absolutePos >= 0)
3523 internalLast();
3524 }
3525 }
3526
3527 // Now move towards the absolute row that we're looking for
3528 while (absolutePos != row) {
3529 if (absolutePos < row) {
3530 if (!internalNext())
3531 break;
3532 }
3533 else {
3534 if (!internalPrevious())
3535 break;
3536 }
3537 }
3538
3539 notifyCursorMoved();
3540
3541 if (isAfterLast() || isBeforeFirst()) {
3542 return false;
3543 } else {
3544 return true;
3545 }
3546 }
3547
3548 /**
3549 * Moves the cursor the specified number of rows from the current
3550 * position, with a positive number moving it forward and a
3551 * negative number moving it backward.
3552 * <P>
3553 * If the number is positive, the cursor moves the specified number of
3554 * rows toward the end of the rowset, starting at the current row.
3555 * For example, the following command, in which
3556 * <code>crs</code> is a <code>CachedRowSetImpl</code> object with 100 rows,
3557 * moves the cursor forward four rows from the current row. If the
3558 * current row is 50, the cursor would move to row 54.
3559 * <PRE><code>
3560 *
3561 * crs.relative(4);
3562 *
3563 * </code> </PRE>
3564 * <P>
3565 * If the number is negative, the cursor moves back toward the beginning
3566 * the specified number of rows, starting at the current row.
3567 * For example, calling the method
3568 * <code>absolute(-1)</code> positions the cursor on the last row,
3569 * <code>absolute(-2)</code> moves it on the next-to-last row, and so on.
3570 * If the <code>CachedRowSetImpl</code> object <code>crs</code> has five rows,
3571 * the following command moves the cursor to the fourth-to-last row, which
3572 * in the case of a rowset with five rows, is also the second row
3573 * from the beginning.
3574 * <PRE><code>
3575 *
3576 * crs.absolute(-4);
3577 *
3578 * </code> </PRE>
3579 *
3580 * If the number specified is larger than the number of rows, the cursor
3581 * will move to the position after the last row. If the number specified
3582 * would move the cursor one or more rows before the first row, the cursor
3583 * moves to the position before the first row. In both cases, this method
3584 * throws an <code>SQLException</code>.
3585 * <P>
3586 * Note: Calling <code>absolute(1)</code> is the same as calling the
3587 * method <code>first()</code>. Calling <code>absolute(-1)</code> is the
3588 * same as calling <code>last()</code>. Calling <code>relative(0)</code>
3589 * is valid, but it does not change the cursor position.
3590 *
3591 * @param rows an <code>int</code> indicating the number of rows to move
3592 * the cursor, starting at the current row; a positive number
3593 * moves the cursor forward; a negative number moves the cursor
3594 * backward; must not move the cursor past the valid
3595 * rows
3596 * @return <code>true</code> if the cursor is on a row in this
3597 * <code>CachedRowSetImpl</code> object; <code>false</code>
3598 * otherwise
3599 * @throws SQLException if there are no rows in this rowset, the cursor is
3600 * positioned either before the first row or after the last row, or
3601 * the rowset is type <code>ResultSet.TYPE_FORWARD_ONLY</code>
3602 */
3603 public boolean relative(int rows) throws SQLException {
3604 if (numRows == 0 || isBeforeFirst() ||
3605 isAfterLast() || getType() == ResultSet.TYPE_FORWARD_ONLY) {
3606 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.relative").toString());
3607 }
3608
3609 if (rows == 0) {
3610 return true;
3611 }
3612
3613 if (rows > 0) { // we are moving forward
3614 if (cursorPos + rows > numRows) {
3615 // fell off the end
3616 afterLast();
3617 } else {
3618 for (int i=0; i < rows; i++) {
3619 if (!internalNext())
3620 break;
3621 }
3622 }
3623 } else { // we are moving backward
3624 if (cursorPos + rows < 0) {
3625 // fell off the front
3626 beforeFirst();
3627 } else {
3628 for (int i=rows; i < 0; i++) {
3629 if (!internalPrevious())
3630 break;
3631 }
3632 }
3633 }
3634 notifyCursorMoved();
3635
3636 if (isAfterLast() || isBeforeFirst()) {
3637 return false;
3638 } else {
3639 return true;
3640 }
3641 }
3642
3643 /**
3644 * Moves this <code>CachedRowSetImpl</code> object's cursor to the
3645 * previous row and returns <code>true</code> if the cursor is on
3646 * a valid row or <code>false</code> if it is not.
3647 * This method also notifies all listeners registered with this
3648 * <code>CachedRowSetImpl</code> object that its cursor has moved.
3649 * <P>
3650 * Note: calling the method <code>previous()</code> is not the same
3651 * as calling the method <code>relative(-1)</code>. This is true
3652 * because it is possible to call <code>previous()</code> from the insert
3653 * row, from after the last row, or from the current row, whereas
3654 * <code>relative</code> may only be called from the current row.
3655 * <P>
3656 * The method <code>previous</code> may used in a <code>while</code>
3657 * loop to iterate through a rowset starting after the last row
3658 * and moving toward the beginning. The loop ends when <code>previous</code>
3659 * returns <code>false</code>, meaning that there are no more rows.
3660 * For example, the following code fragment retrieves all the data in
3661 * the <code>CachedRowSetImpl</code> object <code>crs</code>, which has
3662 * three columns. Note that the cursor must initially be positioned
3663 * after the last row so that the first call to the method
3664 * <code>previous</code> places the cursor on the last line.
3665 * <PRE> <code>
3666 *
3667 * crs.afterLast();
3668 * while (previous()) {
3669 * String name = crs.getString(1);
3670 * int age = crs.getInt(2);
3671 * short ssn = crs.getShort(3);
3672 * System.out.println(name + " " + age + " " + ssn);
3673 * }
3674 *
3675 * </code> </PRE>
3676 * This method throws an <code>SQLException</code> if the cursor is not
3677 * on a row in the rowset, before the first row, or after the last row.
3678 *
3679 * @return <code>true</code> if the cursor is on a valid row;
3680 * <code>false</code> if it is before the first row or after the
3681 * last row
3682 * @throws SQLException if the cursor is not on a valid position or the
3683 * type of this rowset is <code>ResultSet.TYPE_FORWARD_ONLY</code>
3684 */
3685 public boolean previous() throws SQLException {
3686 if (getType() == ResultSet.TYPE_FORWARD_ONLY) {
3687 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.last").toString());
3688 }
3689 /*
3690 * make sure things look sane. The cursor must be
3691 * positioned in the rowset or before first (0) or
3692 * after last (numRows + 1)
3693 */
3694 if (cursorPos < 0 || cursorPos > numRows + 1) {
3695 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
3696 }
3697 // move and notify
3698 boolean ret = this.internalPrevious();
3699 notifyCursorMoved();
3700
3701 return ret;
3702 }
3703
3704 /**
3705 * Moves the cursor to the previous row in this <code>CachedRowSetImpl</code>
3706 * object, skipping past deleted rows that are not visible; returns
3707 * <code>true</code> if the cursor is on a row in this rowset and
3708 * <code>false</code> when the cursor goes before the first row.
3709 * <P>
3710 * This method is called internally by the method <code>previous</code>.
3711 * <P>
3712 * This is a implementation only method and is not required as a standard
3713 * implementation of the <code>CachedRowSet</code> interface.
3714 *
3715 * @return <code>true</code> if the cursor is on a row in this rowset;
3716 * <code>false</code> when the cursor reaches the position before
3717 * the first row
3718 * @throws SQLException if an error occurs
3719 */
3720 protected boolean internalPrevious() throws SQLException {
3721 boolean ret = false;
3722
3723 do {
3724 if (cursorPos > 1) {
3725 --cursorPos;
3726 ret = true;
3727 } else if (cursorPos == 1) {
3728 // decrement to before first
3729 --cursorPos;
3730 ret = false;
3731 break;
3732 }
3733 } while ((getShowDeleted() == false) && (rowDeleted() == true));
3734
3735 /*
3736 * Each call to internalPrevious may move the cursor
3737 * over multiple rows, the absolute postion moves one one row
3738 */
3739 if (ret == true)
3740 --absolutePos;
3741 else
3742 absolutePos = 0;
3743
3744 return ret;
3745 }
3746
3747
3748 //---------------------------------------------------------------------
3749 // Updates
3750 //---------------------------------------------------------------------
3751
3752 /**
3753 * Indicates whether the current row of this <code>CachedRowSetImpl</code>
3754 * object has been updated. The value returned
3755 * depends on whether this rowset can detect updates: <code>false</code>
3756 * will always be returned if it does not detect updates.
3757 *
3758 * @return <code>true</code> if the row has been visibly updated
3759 * by the owner or another and updates are detected;
3760 * <code>false</code> otherwise
3761 * @throws SQLException if the cursor is on the insert row or not
3762 * not on a valid row
3763 *
3764 * @see DatabaseMetaData#updatesAreDetected
3765 */
3766 public boolean rowUpdated() throws SQLException {
3767 // make sure the cursor is on a valid row
3768 checkCursor();
3769 if (onInsertRow == true) {
3770 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3771 }
3772 return(((Row)getCurrentRow()).getUpdated());
3773 }
3774
3775 /**
3776 * Indicates whether the designated column of the current row of
3777 * this <code>CachedRowSetImpl</code> object has been updated. The
3778 * value returned depends on whether this rowset can detcted updates:
3779 * <code>false</code> will always be returned if it does not detect updates.
3780 *
3781 * @param idx the index identifier of the column that may be have been updated.
3782 * @return <code>true</code> is the designated column has been updated
3783 * and the rowset detects updates; <code>false</code> if the rowset has not
3784 * been updated or the rowset does not detect updates
3785 * @throws SQLException if the cursor is on the insert row or not
3786 * on a valid row
3787 * @see DatabaseMetaData#updatesAreDetected
3788 */
3789 public boolean columnUpdated(int idx) throws SQLException {
3790 // make sure the cursor is on a valid row
3791 checkCursor();
3792 if (onInsertRow == true) {
3793 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3794 }
3795 return (((Row)getCurrentRow()).getColUpdated(idx - 1));
3796 }
3797
3798 /**
3799 * Indicates whether the designated column of the current row of
3800 * this <code>CachedRowSetImpl</code> object has been updated. The
3801 * value returned depends on whether this rowset can detcted updates:
3802 * <code>false</code> will always be returned if it does not detect updates.
3803 *
3804 * @param columnName the <code>String</code> column name column that may be have
3805 * been updated.
3806 * @return <code>true</code> is the designated column has been updated
3807 * and the rowset detects updates; <code>false</code> if the rowset has not
3808 * been updated or the rowset does not detect updates
3809 * @throws SQLException if the cursor is on the insert row or not
3810 * on a valid row
3811 * @see DatabaseMetaData#updatesAreDetected
3812 */
3813 public boolean columnUpdated(String columnName) throws SQLException {
3814 return columnUpdated(getColIdxByName(columnName));
3815 }
3816
3817 /**
3818 * Indicates whether the current row has been inserted. The value returned
3819 * depends on whether or not the rowset can detect visible inserts.
3820 *
3821 * @return <code>true</code> if a row has been inserted and inserts are detected;
3822 * <code>false</code> otherwise
3823 * @throws SQLException if the cursor is on the insert row or not
3824 * not on a valid row
3825 *
3826 * @see DatabaseMetaData#insertsAreDetected
3827 */
3828 public boolean rowInserted() throws SQLException {
3829 // make sure the cursor is on a valid row
3830 checkCursor();
3831 if (onInsertRow == true) {
3832 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString());
3833 }
3834 return(((Row)getCurrentRow()).getInserted());
3835 }
3836
3837 /**
3838 * Indicates whether the current row has been deleted. A deleted row
3839 * may leave a visible "hole" in a rowset. This method can be used to
3840 * detect such holes if the rowset can detect deletions. This method
3841 * will always return <code>false</code> if this rowset cannot detect
3842 * deletions.
3843 *
3844 * @return <code>true</code> if (1)the current row is blank, indicating that
3845 * the row has been deleted, and (2)deletions are detected;
3846 * <code>false</code> otherwise
3847 * @throws SQLException if the cursor is on a valid row in this rowset
3848 * @see DatabaseMetaData#deletesAreDetected
3849 */
3850 public boolean rowDeleted() throws SQLException {
3851 // make sure the cursor is on a valid row
3852
3853 if (isAfterLast() == true ||
3854 isBeforeFirst() == true ||
3855 onInsertRow == true) {
3856
3857 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidcp").toString());
3858 }
3859 return(((Row)getCurrentRow()).getDeleted());
3860 }
3861
3862 /**
3863 * Indicates whether the given SQL data type is a numberic type.
3864 *
3865 * @param type one of the constants from <code>java.sql.Types</code>
3866 * @return <code>true</code> if the given type is <code>NUMERIC</code>,'
3867 * <code>DECIMAL</code>, <code>BIT</code>, <code>TINYINT</code>,
3868 * <code>SMALLINT</code>, <code>INTEGER</code>, <code>BIGINT</code>,
3869 * <code>REAL</code>, <code>DOUBLE</code>, or <code>FLOAT</code>;
3870 * <code>false</code> otherwise
3871 */
3872 private boolean isNumeric(int type) {
3873 switch (type) {
3874 case java.sql.Types.NUMERIC:
3875 case java.sql.Types.DECIMAL:
3876 case java.sql.Types.BIT:
3877 case java.sql.Types.TINYINT:
3878 case java.sql.Types.SMALLINT:
3879 case java.sql.Types.INTEGER:
3880 case java.sql.Types.BIGINT:
3881 case java.sql.Types.REAL:
3882 case java.sql.Types.DOUBLE:
3883 case java.sql.Types.FLOAT:
3884 return true;
3885 default:
3886 return false;
3887 }
3888 }
3889
3890 /**
3891 * Indicates whether the given SQL data type is a string type.
3892 *
3893 * @param type one of the constants from <code>java.sql.Types</code>
3894 * @return <code>true</code> if the given type is <code>CHAR</code>,'
3895 * <code>VARCHAR</code>, or <code>LONGVARCHAR</code>;
3896 * <code>false</code> otherwise
3897 */
3898 private boolean isString(int type) {
3899 switch (type) {
3900 case java.sql.Types.CHAR:
3901 case java.sql.Types.VARCHAR:
3902 case java.sql.Types.LONGVARCHAR:
3903 return true;
3904 default:
3905 return false;
3906 }
3907 }
3908
3909 /**
3910 * Indicates whether the given SQL data type is a binary type.
3911 *
3912 * @param type one of the constants from <code>java.sql.Types</code>
3913 * @return <code>true</code> if the given type is <code>BINARY</code>,'
3914 * <code>VARBINARY</code>, or <code>LONGVARBINARY</code>;
3915 * <code>false</code> otherwise
3916 */
3917 private boolean isBinary(int type) {
3918 switch (type) {
3919 case java.sql.Types.BINARY:
3920 case java.sql.Types.VARBINARY:
3921 case java.sql.Types.LONGVARBINARY:
3922 return true;
3923 default:
3924 return false;
3925 }
3926 }
3927
3928 /**
3929 * Indicates whether the given SQL data type is a temporal type.
3930 * This method is called internally by the conversion methods
3931 * <code>convertNumeric</code> and <code>convertTemporal</code>.
3932 *
3933 * @param type one of the constants from <code>java.sql.Types</code>
3934 * @return <code>true</code> if the given type is <code>DATE</code>,
3935 * <code>TIME</code>, or <code>TIMESTAMP</code>;
3936 * <code>false</code> otherwise
3937 */
3938 private boolean isTemporal(int type) {
3939 switch (type) {
3940 case java.sql.Types.DATE:
3941 case java.sql.Types.TIME:
3942 case java.sql.Types.TIMESTAMP:
3943 return true;
3944 default:
3945 return false;
3946 }
3947 }
3948
3949 /**
3950 * Indicates whether the given SQL data type is a boolean type.
3951 * This method is called internally by the conversion methods
3952 * <code>convertNumeric</code> and <code>convertBoolean</code>.
3953 *
3954 * @param type one of the constants from <code>java.sql.Types</code>
3955 * @return <code>true</code> if the given type is <code>BIT</code>,
3956 * , or <code>BOOLEAN</code>;
3957 * <code>false</code> otherwise
3958 */
3959 private boolean isBoolean(int type) {
3960 switch (type) {
3961 case java.sql.Types.BIT:
3962 case java.sql.Types.BOOLEAN:
3963 return true;
3964 default:
3965 return false;
3966 }
3967 }
3968
3969
3970 /**
3971 * Converts the given <code>Object</code> in the Java programming language
3972 * to the standard mapping for the specified SQL target data type.
3973 * The conversion must be to a string or numeric type, but there are no
3974 * restrictions on the type to be converted. If the source type and target
3975 * type are the same, the given object is simply returned.
3976 *
3977 * @param srcObj the <code>Object</code> in the Java programming language
3978 * that is to be converted to the target type
3979 * @param srcType the data type that is the standard mapping in SQL of the
3980 * object to be converted; must be one of the constants in
3981 * <code>java.sql.Types</code>
3982 * @param trgType the SQL data type to which to convert the given object;
3983 * must be one of the following constants in
3984 * <code>java.sql.Types</code>: <code>NUMERIC</code>,
3985 * <code>DECIMAL</code>, <code>BIT</code>, <code>TINYINT</code>,
3986 * <code>SMALLINT</code>, <code>INTEGER</code>, <code>BIGINT</code>,
3987 * <code>REAL</code>, <code>DOUBLE</code>, <code>FLOAT</code>,
3988 * <code>VARCHAR</code>, <code>LONGVARCHAR</code>, or <code>CHAR</code>
3989 * @return an <code>Object</code> value.that is
3990 * the standard object mapping for the target SQL type
3991 * @throws SQLException if the given target type is not one of the string or
3992 * numeric types in <code>java.sql.Types</code>
3993 */
3994 private Object convertNumeric(Object srcObj, int srcType,
3995 int trgType) throws SQLException {
3996
3997 if (srcType == trgType) {
3998 return srcObj;
3999 }
4000
4001 if (isNumeric(trgType) == false && isString(trgType) == false) {
4002 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
4003 }
4004
4005 try {
4006 switch (trgType) {
4007 case java.sql.Types.BIT:
4008 Integer i = Integer.valueOf(srcObj.toString().trim());
4009 return i.equals(Integer.valueOf((int)0)) ?
4010 Boolean.valueOf(false) :
4011 Boolean.valueOf(true);
4012 case java.sql.Types.TINYINT:
4013 return Byte.valueOf(srcObj.toString().trim());
4014 case java.sql.Types.SMALLINT:
4015 return Short.valueOf(srcObj.toString().trim());
4016 case java.sql.Types.INTEGER:
4017 return Integer.valueOf(srcObj.toString().trim());
4018 case java.sql.Types.BIGINT:
4019 return Long.valueOf(srcObj.toString().trim());
4020 case java.sql.Types.NUMERIC:
4021 case java.sql.Types.DECIMAL:
4022 return new BigDecimal(srcObj.toString().trim());
4023 case java.sql.Types.REAL:
4024 case java.sql.Types.FLOAT:
4025 return new Float(srcObj.toString().trim());
4026 case java.sql.Types.DOUBLE:
4027 return new Double(srcObj.toString().trim());
4028 case java.sql.Types.CHAR:
4029 case java.sql.Types.VARCHAR:
4030 case java.sql.Types.LONGVARCHAR:
4031 return srcObj.toString();
4032 default:
4033 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString()+ trgType);
4034 }
4035 } catch (NumberFormatException ex) {
4036 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
4037 }
4038 }
4039
4040 /**
4041 * Converts the given <code>Object</code> in the Java programming language
4042 * to the standard object mapping for the specified SQL target data type.
4043 * The conversion must be to a string or temporal type, and there are also
4044 * restrictions on the type to be converted.
4045 * <P>
4046 * <TABLE ALIGN="CENTER" BORDER CELLPADDING=10 BORDERCOLOR="#0000FF"
4047 * <CAPTION ALIGN="CENTER"><B>Parameters and Return Values</B></CAPTION>
4048 * <TR>
4049 * <TD><B>Source SQL Type</B>
4050 * <TD><B>Target SQL Type</B>
4051 * <TD><B>Object Returned</B>
4052 * </TR>
4053 * <TR>
4054 * <TD><code>TIMESTAMP</code>
4055 * <TD><code>DATE</code>
4056 * <TD><code>java.sql.Date</code>
4057 * </TR>
4058 * <TR>
4059 * <TD><code>TIMESTAMP</code>
4060 * <TD><code>TIME</code>
4061 * <TD><code>java.sql.Time</code>
4062 * </TR>
4063 * <TR>
4064 * <TD><code>TIME</code>
4065 * <TD><code>TIMESTAMP</code>
4066 * <TD><code>java.sql.Timestamp</code>
4067 * </TR>
4068 * <TR>
4069 * <TD><code>DATE</code>, <code>TIME</code>, or <code>TIMESTAMP</code>
4070 * <TD><code>CHAR</code>, <code>VARCHAR</code>, or <code>LONGVARCHAR</code>
4071 * <TD><code>java.lang.String</code>
4072 * </TR>
4073 * </TABLE>
4074 * <P>
4075 * If the source type and target type are the same,
4076 * the given object is simply returned.
4077 *
4078 * @param srcObj the <code>Object</code> in the Java programming language
4079 * that is to be converted to the target type
4080 * @param srcType the data type that is the standard mapping in SQL of the
4081 * object to be converted; must be one of the constants in
4082 * <code>java.sql.Types</code>
4083 * @param trgType the SQL data type to which to convert the given object;
4084 * must be one of the following constants in
4085 * <code>java.sql.Types</code>: <code>DATE</code>,
4086 * <code>TIME</code>, <code>TIMESTAMP</code>, <code>CHAR</code>,
4087 * <code>VARCHAR</code>, or <code>LONGVARCHAR</code>
4088 * @return an <code>Object</code> value.that is
4089 * the standard object mapping for the target SQL type
4090 * @throws SQLException if the given target type is not one of the string or
4091 * temporal types in <code>java.sql.Types</code>
4092 */
4093 private Object convertTemporal(Object srcObj,
4094 int srcType, int trgType) throws SQLException {
4095
4096 if (srcType == trgType) {
4097 return srcObj;
4098 }
4099
4100 if (isNumeric(trgType) == true ||
4101 (isString(trgType) == false && isTemporal(trgType) == false)) {
4102 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4103 }
4104
4105 try {
4106 switch (trgType) {
4107 case java.sql.Types.DATE:
4108 if (srcType == java.sql.Types.TIMESTAMP) {
4109 return new java.sql.Date(((java.sql.Timestamp)srcObj).getTime());
4110 } else {
4111 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4112 }
4113 case java.sql.Types.TIMESTAMP:
4114 if (srcType == java.sql.Types.TIME) {
4115 return new Timestamp(((java.sql.Time)srcObj).getTime());
4116 } else {
4117 return new Timestamp(((java.sql.Date)srcObj).getTime());
4118 }
4119 case java.sql.Types.TIME:
4120 if (srcType == java.sql.Types.TIMESTAMP) {
4121 return new Time(((java.sql.Timestamp)srcObj).getTime());
4122 } else {
4123 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4124 }
4125 case java.sql.Types.CHAR:
4126 case java.sql.Types.VARCHAR:
4127 case java.sql.Types.LONGVARCHAR:
4128 return srcObj.toString();
4129 default:
4130 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4131 }
4132 } catch (NumberFormatException ex) {
4133 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4134 }
4135
4136 }
4137
4138 /**
4139 * Converts the given <code>Object</code> in the Java programming language
4140 * to the standard mapping for the specified SQL target data type.
4141 * The conversion must be to a string or numeric type, but there are no
4142 * restrictions on the type to be converted. If the source type and target
4143 * type are the same, the given object is simply returned.
4144 *
4145 * @param srcObj the <code>Object</code> in the Java programming language
4146 * that is to be converted to the target type
4147 * @param srcType the data type that is the standard mapping in SQL of the
4148 * object to be converted; must be one of the constants in
4149 * <code>java.sql.Types</code>
4150 * @param trgType the SQL data type to which to convert the given object;
4151 * must be one of the following constants in
4152 * <code>java.sql.Types</code>: <code>BIT</code>,
4153 * or <code>BOOLEAN</code>
4154 * @return an <code>Object</code> value.that is
4155 * the standard object mapping for the target SQL type
4156 * @throws SQLException if the given target type is not one of the Boolean
4157 * types in <code>java.sql.Types</code>
4158 */
4159 private Object convertBoolean(Object srcObj, int srcType,
4160 int trgType) throws SQLException {
4161
4162 if (srcType == trgType) {
4163 return srcObj;
4164 }
4165
4166 if (isNumeric(trgType) == true ||
4167 (isString(trgType) == false && isBoolean(trgType) == false)) {
4168 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4169 }
4170
4171
4172 try {
4173 switch (trgType) {
4174 case java.sql.Types.BIT:
4175 Integer i = Integer.valueOf(srcObj.toString().trim());
4176 return i.equals(Integer.valueOf((int)0)) ?
4177 Boolean.valueOf(false) :
4178 Boolean.valueOf(true);
4179 case java.sql.Types.BOOLEAN:
4180 return Boolean.valueOf(srcObj.toString().trim());
4181 default:
4182 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString()+ trgType);
4183 }
4184 } catch (NumberFormatException ex) {
4185 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString() + trgType);
4186 }
4187 }
4188
4189 /**
4190 * Sets the designated nullable column in the current row or the
4191 * insert row of this <code>CachedRowSetImpl</code> object with
4192 * <code>null</code> value.
4193 * <P>
4194 * This method updates a column value in the current row or the insert
4195 * row of this rowset; however, another method must be called to complete
4196 * the update process. If the cursor is on a row in the rowset, the
4197 * method {@link #updateRow} must be called to mark the row as updated
4198 * and to notify listeners that the row has changed.
4199 * If the cursor is on the insert row, the method {@link #insertRow}
4200 * must be called to insert the new row into this rowset and to notify
4201 * listeners that a row has changed.
4202 * <P>
4203 * In order to propagate updates in this rowset to the underlying
4204 * data source, an application must call the method {@link #acceptChanges}
4205 * after it calls either <code>updateRow</code> or <code>insertRow</code>.
4206 *
4207 * @param columnIndex the first column is <code>1</code>, the second
4208 * is <code>2</code>, and so on; must be <code>1</code> or larger
4209 * and equal to or less than the number of columns in this rowset
4210 * @throws SQLException if (1) the given column index is out of bounds,
4211 * (2) the cursor is not on one of this rowset's rows or its
4212 * insert row, or (3) this rowset is
4213 * <code>ResultSet.CONCUR_READ_ONLY</code>
4214 */
4215 public void updateNull(int columnIndex) throws SQLException {
4216 // sanity check.
4217 checkIndex(columnIndex);
4218 // make sure the cursor is on a valid row
4219 checkCursor();
4220
4221 BaseRow row = getCurrentRow();
4222 row.setColumnObject(columnIndex, null);
4223
4224 }
4225
4226 /**
4227 * Sets the designated column in either the current row or the insert
4228 * row of this <code>CachedRowSetImpl</code> object with the given
4229 * <code>boolean</code> value.
4230 * <P>
4231 * This method updates a column value in the current row or the insert
4232 * row of this rowset, but it does not update the database.
4233 * If the cursor is on a row in the rowset, the
4234 * method {@link #updateRow} must be called to update the database.
4235 * If the cursor is on the insert row, the method {@link #insertRow}
4236 * must be called, which will insert the new row into both this rowset
4237 * and the database. Both of these methods must be called before the
4238 * cursor moves to another row.
4239 *
4240 * @param columnIndex the first column is <code>1</code>, the second
4241 * is <code>2</code>, and so on; must be <code>1</code> or larger
4242 * and equal to or less than the number of columns in this rowset
4243 * @param x the new column value
4244 * @throws SQLException if (1) the given column index is out of bounds,
4245 * (2) the cursor is not on one of this rowset's rows or its
4246 * insert row, or (3) this rowset is
4247 * <code>ResultSet.CONCUR_READ_ONLY</code>
4248 */
4249 public void updateBoolean(int columnIndex, boolean x) throws SQLException {
4250 // sanity check.
4251 checkIndex(columnIndex);
4252 // make sure the cursor is on a valid row
4253 checkCursor();
4254 Object obj = convertBoolean(Boolean.valueOf(x),
4255 java.sql.Types.BIT,
4256 RowSetMD.getColumnType(columnIndex));
4257
4258 getCurrentRow().setColumnObject(columnIndex, obj);
4259 }
4260
4261 /**
4262 * Sets the designated column in either the current row or the insert
4263 * row of this <code>CachedRowSetImpl</code> object with the given
4264 * <code>byte</code> value.
4265 * <P>
4266 * This method updates a column value in the current row or the insert
4267 * row of this rowset, but it does not update the database.
4268 * If the cursor is on a row in the rowset, the
4269 * method {@link #updateRow} must be called to update the database.
4270 * If the cursor is on the insert row, the method {@link #insertRow}
4271 * must be called, which will insert the new row into both this rowset
4272 * and the database. Both of these methods must be called before the
4273 * cursor moves to another row.
4274 *
4275 * @param columnIndex the first column is <code>1</code>, the second
4276 * is <code>2</code>, and so on; must be <code>1</code> or larger
4277 * and equal to or less than the number of columns in this rowset
4278 * @param x the new column value
4279 * @throws SQLException if (1) the given column index is out of bounds,
4280 * (2) the cursor is not on one of this rowset's rows or its
4281 * insert row, or (3) this rowset is
4282 * <code>ResultSet.CONCUR_READ_ONLY</code>
4283 */
4284 public void updateByte(int columnIndex, byte x) throws SQLException {
4285 // sanity check.
4286 checkIndex(columnIndex);
4287 // make sure the cursor is on a valid row
4288 checkCursor();
4289
4290 Object obj = convertNumeric(Byte.valueOf(x),
4291 java.sql.Types.TINYINT,
4292 RowSetMD.getColumnType(columnIndex));
4293
4294 getCurrentRow().setColumnObject(columnIndex, obj);
4295 }
4296
4297 /**
4298 * Sets the designated column in either the current row or the insert
4299 * row of this <code>CachedRowSetImpl</code> object with the given
4300 * <code>short</code> value.
4301 * <P>
4302 * This method updates a column value in the current row or the insert
4303 * row of this rowset, but it does not update the database.
4304 * If the cursor is on a row in the rowset, the
4305 * method {@link #updateRow} must be called to update the database.
4306 * If the cursor is on the insert row, the method {@link #insertRow}
4307 * must be called, which will insert the new row into both this rowset
4308 * and the database. Both of these methods must be called before the
4309 * cursor moves to another row.
4310 *
4311 * @param columnIndex the first column is <code>1</code>, the second
4312 * is <code>2</code>, and so on; must be <code>1</code> or larger
4313 * and equal to or less than the number of columns in this rowset
4314 * @param x the new column value
4315 * @throws SQLException if (1) the given column index is out of bounds,
4316 * (2) the cursor is not on one of this rowset's rows or its
4317 * insert row, or (3) this rowset is
4318 * <code>ResultSet.CONCUR_READ_ONLY</code>
4319 */
4320 public void updateShort(int columnIndex, short x) throws SQLException {
4321 // sanity check.
4322 checkIndex(columnIndex);
4323 // make sure the cursor is on a valid row
4324 checkCursor();
4325
4326 Object obj = convertNumeric(Short.valueOf(x),
4327 java.sql.Types.SMALLINT,
4328 RowSetMD.getColumnType(columnIndex));
4329
4330 getCurrentRow().setColumnObject(columnIndex, obj);
4331 }
4332
4333 /**
4334 * Sets the designated column in either the current row or the insert
4335 * row of this <code>CachedRowSetImpl</code> object with the given
4336 * <code>int</code> value.
4337 * <P>
4338 * This method updates a column value in the current row or the insert
4339 * row of this rowset, but it does not update the database.
4340 * If the cursor is on a row in the rowset, the
4341 * method {@link #updateRow} must be called to update the database.
4342 * If the cursor is on the insert row, the method {@link #insertRow}
4343 * must be called, which will insert the new row into both this rowset
4344 * and the database. Both of these methods must be called before the
4345 * cursor moves to another row.
4346 *
4347 * @param columnIndex the first column is <code>1</code>, the second
4348 * is <code>2</code>, and so on; must be <code>1</code> or larger
4349 * and equal to or less than the number of columns in this rowset
4350 * @param x the new column value
4351 * @throws SQLException if (1) the given column index is out of bounds,
4352 * (2) the cursor is not on one of this rowset's rows or its
4353 * insert row, or (3) this rowset is
4354 * <code>ResultSet.CONCUR_READ_ONLY</code>
4355 */
4356 public void updateInt(int columnIndex, int x) throws SQLException {
4357 // sanity check.
4358 checkIndex(columnIndex);
4359 // make sure the cursor is on a valid row
4360 checkCursor();
4361 Object obj = convertNumeric(Integer.valueOf(x),
4362 java.sql.Types.INTEGER,
4363 RowSetMD.getColumnType(columnIndex));
4364
4365 getCurrentRow().setColumnObject(columnIndex, obj);
4366 }
4367
4368 /**
4369 * Sets the designated column in either the current row or the insert
4370 * row of this <code>CachedRowSetImpl</code> object with the given
4371 * <code>long</code> value.
4372 * <P>
4373 * This method updates a column value in the current row or the insert
4374 * row of this rowset, but it does not update the database.
4375 * If the cursor is on a row in the rowset, the
4376 * method {@link #updateRow} must be called to update the database.
4377 * If the cursor is on the insert row, the method {@link #insertRow}
4378 * must be called, which will insert the new row into both this rowset
4379 * and the database. Both of these methods must be called before the
4380 * cursor moves to another row.
4381 *
4382 * @param columnIndex the first column is <code>1</code>, the second
4383 * is <code>2</code>, and so on; must be <code>1</code> or larger
4384 * and equal to or less than the number of columns in this rowset
4385 * @param x the new column value
4386 * @throws SQLException if (1) the given column index is out of bounds,
4387 * (2) the cursor is not on one of this rowset's rows or its
4388 * insert row, or (3) this rowset is
4389 * <code>ResultSet.CONCUR_READ_ONLY</code>
4390 */
4391 public void updateLong(int columnIndex, long x) throws SQLException {
4392 // sanity check.
4393 checkIndex(columnIndex);
4394 // make sure the cursor is on a valid row
4395 checkCursor();
4396
4397 Object obj = convertNumeric(Long.valueOf(x),
4398 java.sql.Types.BIGINT,
4399 RowSetMD.getColumnType(columnIndex));
4400
4401 getCurrentRow().setColumnObject(columnIndex, obj);
4402
4403 }
4404
4405 /**
4406 * Sets the designated column in either the current row or the insert
4407 * row of this <code>CachedRowSetImpl</code> object with the given
4408 * <code>float</code> value.
4409 * <P>
4410 * This method updates a column value in the current row or the insert
4411 * row of this rowset, but it does not update the database.
4412 * If the cursor is on a row in the rowset, the
4413 * method {@link #updateRow} must be called to update the database.
4414 * If the cursor is on the insert row, the method {@link #insertRow}
4415 * must be called, which will insert the new row into both this rowset
4416 * and the database. Both of these methods must be called before the
4417 * cursor moves to another row.
4418 *
4419 * @param columnIndex the first column is <code>1</code>, the second
4420 * is <code>2</code>, and so on; must be <code>1</code> or larger
4421 * and equal to or less than the number of columns in this rowset
4422 * @param x the new column value
4423 * @throws SQLException if (1) the given column index is out of bounds,
4424 * (2) the cursor is not on one of this rowset's rows or its
4425 * insert row, or (3) this rowset is
4426 * <code>ResultSet.CONCUR_READ_ONLY</code>
4427 */
4428 public void updateFloat(int columnIndex, float x) throws SQLException {
4429 // sanity check.
4430 checkIndex(columnIndex);
4431 // make sure the cursor is on a valid row
4432 checkCursor();
4433
4434 Object obj = convertNumeric(new Float(x),
4435 java.sql.Types.REAL,
4436 RowSetMD.getColumnType(columnIndex));
4437
4438 getCurrentRow().setColumnObject(columnIndex, obj);
4439 }
4440
4441 /**
4442 * Sets the designated column in either the current row or the insert
4443 * row of this <code>CachedRowSetImpl</code> object with the given
4444 * <code>double</code> value.
4445 *
4446 * This method updates a column value in either the current row or
4447 * the insert row of this rowset, but it does not update the
4448 * database. If the cursor is on a row in the rowset, the
4449 * method {@link #updateRow} must be called to update the database.
4450 * If the cursor is on the insert row, the method {@link #insertRow}
4451 * must be called, which will insert the new row into both this rowset
4452 * and the database. Both of these methods must be called before the
4453 * cursor moves to another row.
4454 *
4455 * @param columnIndex the first column is <code>1</code>, the second
4456 * is <code>2</code>, and so on; must be <code>1</code> or larger
4457 * and equal to or less than the number of columns in this rowset
4458 * @param x the new column value
4459 * @throws SQLException if (1) the given column index is out of bounds,
4460 * (2) the cursor is not on one of this rowset's rows or its
4461 * insert row, or (3) this rowset is
4462 * <code>ResultSet.CONCUR_READ_ONLY</code>
4463 */
4464 public void updateDouble(int columnIndex, double x) throws SQLException {
4465 // sanity check.
4466 checkIndex(columnIndex);
4467 // make sure the cursor is on a valid row
4468 checkCursor();
4469 Object obj = convertNumeric(new Double(x),
4470 java.sql.Types.DOUBLE,
4471 RowSetMD.getColumnType(columnIndex));
4472
4473 getCurrentRow().setColumnObject(columnIndex, obj);
4474 }
4475
4476 /**
4477 * Sets the designated column in either the current row or the insert
4478 * row of this <code>CachedRowSetImpl</code> object with the given
4479 * <code>java.math.BigDecimal</code> object.
4480 * <P>
4481 * This method updates a column value in the current row or the insert
4482 * row of this rowset, but it does not update the database.
4483 * If the cursor is on a row in the rowset, the
4484 * method {@link #updateRow} must be called to update the database.
4485 * If the cursor is on the insert row, the method {@link #insertRow}
4486 * must be called, which will insert the new row into both this rowset
4487 * and the database. Both of these methods must be called before the
4488 * cursor moves to another row.
4489 *
4490 * @param columnIndex the first column is <code>1</code>, the second
4491 * is <code>2</code>, and so on; must be <code>1</code> or larger
4492 * and equal to or less than the number of columns in this rowset
4493 * @param x the new column value
4494 * @throws SQLException if (1) the given column index is out of bounds,
4495 * (2) the cursor is not on one of this rowset's rows or its
4496 * insert row, or (3) this rowset is
4497 * <code>ResultSet.CONCUR_READ_ONLY</code>
4498 */
4499 public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException {
4500 // sanity check.
4501 checkIndex(columnIndex);
4502 // make sure the cursor is on a valid row
4503 checkCursor();
4504
4505 Object obj = convertNumeric(x,
4506 java.sql.Types.NUMERIC,
4507 RowSetMD.getColumnType(columnIndex));
4508
4509 getCurrentRow().setColumnObject(columnIndex, obj);
4510 }
4511
4512 /**
4513 * Sets the designated column in either the current row or the insert
4514 * row of this <code>CachedRowSetImpl</code> object with the given
4515 * <code>String</code> object.
4516 * <P>
4517 * This method updates a column value in either the current row or
4518 * the insert row of this rowset, but it does not update the
4519 * database. If the cursor is on a row in the rowset, the
4520 * method {@link #updateRow} must be called to mark the row as updated.
4521 * If the cursor is on the insert row, the method {@link #insertRow}
4522 * must be called to insert the new row into this rowset and mark it
4523 * as inserted. Both of these methods must be called before the
4524 * cursor moves to another row.
4525 * <P>
4526 * The method <code>acceptChanges</code> must be called if the
4527 * updated values are to be written back to the underlying database.
4528 *
4529 * @param columnIndex the first column is <code>1</code>, the second
4530 * is <code>2</code>, and so on; must be <code>1</code> or larger
4531 * and equal to or less than the number of columns in this rowset
4532 * @param x the new column value
4533 * @throws SQLException if (1) the given column index is out of bounds,
4534 * (2) the cursor is not on one of this rowset's rows or its
4535 * insert row, or (3) this rowset is
4536 * <code>ResultSet.CONCUR_READ_ONLY</code>
4537 */
4538 public void updateString(int columnIndex, String x) throws SQLException {
4539 // sanity check.
4540 checkIndex(columnIndex);
4541 // make sure the cursor is on a valid row
4542 checkCursor();
4543
4544 getCurrentRow().setColumnObject(columnIndex, x);
4545 }
4546
4547 /**
4548 * Sets the designated column in either the current row or the insert
4549 * row of this <code>CachedRowSetImpl</code> object with the given
4550 * <code>byte</code> array.
4551 *
4552 * This method updates a column value in either the current row or
4553 * the insert row of this rowset, but it does not update the
4554 * database. If the cursor is on a row in the rowset, the
4555 * method {@link #updateRow} must be called to update the database.
4556 * If the cursor is on the insert row, the method {@link #insertRow}
4557 * must be called, which will insert the new row into both this rowset
4558 * and the database. Both of these methods must be called before the
4559 * cursor moves to another row.
4560 *
4561 * @param columnIndex the first column is <code>1</code>, the second
4562 * is <code>2</code>, and so on; must be <code>1</code> or larger
4563 * and equal to or less than the number of columns in this rowset
4564 * @param x the new column value
4565 * @throws SQLException if (1) the given column index is out of bounds,
4566 * (2) the cursor is not on one of this rowset's rows or its
4567 * insert row, or (3) this rowset is
4568 * <code>ResultSet.CONCUR_READ_ONLY</code>
4569 */
4570 public void updateBytes(int columnIndex, byte x[]) throws SQLException {
4571 // sanity check.
4572 checkIndex(columnIndex);
4573 // make sure the cursor is on a valid row
4574 checkCursor();
4575
4576 if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4577 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4578 }
4579
4580 getCurrentRow().setColumnObject(columnIndex, x);
4581 }
4582
4583 /**
4584 * Sets the designated column in either the current row or the insert
4585 * row of this <code>CachedRowSetImpl</code> object with the given
4586 * <code>Date</code> object.
4587 *
4588 * This method updates a column value in either the current row or
4589 * the insert row of this rowset, but it does not update the
4590 * database. If the cursor is on a row in the rowset, the
4591 * method {@link #updateRow} must be called to update the database.
4592 * If the cursor is on the insert row, the method {@link #insertRow}
4593 * must be called, which will insert the new row into both this rowset
4594 * and the database. Both of these methods must be called before the
4595 * cursor moves to another row.
4596 *
4597 * @param columnIndex the first column is <code>1</code>, the second
4598 * is <code>2</code>, and so on; must be <code>1</code> or larger
4599 * and equal to or less than the number of columns in this rowset
4600 * @param x the new column value
4601 * @throws SQLException if (1) the given column index is out of bounds,
4602 * (2) the cursor is not on one of this rowset's rows or its
4603 * insert row, (3) the type of the designated column is not
4604 * an SQL <code>DATE</code> or <code>TIMESTAMP</code>, or
4605 * (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4606 */
4607 public void updateDate(int columnIndex, java.sql.Date x) throws SQLException {
4608 // sanity check.
4609 checkIndex(columnIndex);
4610 // make sure the cursor is on a valid row
4611 checkCursor();
4612
4613 Object obj = convertTemporal(x,
4614 java.sql.Types.DATE,
4615 RowSetMD.getColumnType(columnIndex));
4616
4617 getCurrentRow().setColumnObject(columnIndex, obj);
4618 }
4619
4620 /**
4621 * Sets the designated column in either the current row or the insert
4622 * row of this <code>CachedRowSetImpl</code> object with the given
4623 * <code>Time</code> object.
4624 *
4625 * This method updates a column value in either the current row or
4626 * the insert row of this rowset, but it does not update the
4627 * database. If the cursor is on a row in the rowset, the
4628 * method {@link #updateRow} must be called to update the database.
4629 * If the cursor is on the insert row, the method {@link #insertRow}
4630 * must be called, which will insert the new row into both this rowset
4631 * and the database. Both of these methods must be called before the
4632 * cursor moves to another row.
4633 *
4634 * @param columnIndex the first column is <code>1</code>, the second
4635 * is <code>2</code>, and so on; must be <code>1</code> or larger
4636 * and equal to or less than the number of columns in this rowset
4637 * @param x the new column value
4638 * @throws SQLException if (1) the given column index is out of bounds,
4639 * (2) the cursor is not on one of this rowset's rows or its
4640 * insert row, (3) the type of the designated column is not
4641 * an SQL <code>TIME</code> or <code>TIMESTAMP</code>, or
4642 * (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4643 */
4644 public void updateTime(int columnIndex, java.sql.Time x) throws SQLException {
4645 // sanity check.
4646 checkIndex(columnIndex);
4647 // make sure the cursor is on a valid row
4648 checkCursor();
4649
4650 Object obj = convertTemporal(x,
4651 java.sql.Types.TIME,
4652 RowSetMD.getColumnType(columnIndex));
4653
4654 getCurrentRow().setColumnObject(columnIndex, obj);
4655 }
4656
4657 /**
4658 * Sets the designated column in either the current row or the insert
4659 * row of this <code>CachedRowSetImpl</code> object with the given
4660 * <code>Timestamp</code> object.
4661 *
4662 * This method updates a column value in either the current row or
4663 * the insert row of this rowset, but it does not update the
4664 * database. If the cursor is on a row in the rowset, the
4665 * method {@link #updateRow} must be called to update the database.
4666 * If the cursor is on the insert row, the method {@link #insertRow}
4667 * must be called, which will insert the new row into both this rowset
4668 * and the database. Both of these methods must be called before the
4669 * cursor moves to another row.
4670 *
4671 * @param columnIndex the first column is <code>1</code>, the second
4672 * is <code>2</code>, and so on; must be <code>1</code> or larger
4673 * and equal to or less than the number of columns in this rowset
4674 * @param x the new column value
4675 * @throws SQLException if (1) the given column index is out of bounds,
4676 * (2) the cursor is not on one of this rowset's rows or its
4677 * insert row, (3) the type of the designated column is not
4678 * an SQL <code>DATE</code>, <code>TIME</code>, or
4679 * <code>TIMESTAMP</code>, or (4) this rowset is
4680 * <code>ResultSet.CONCUR_READ_ONLY</code>
4681 */
4682 public void updateTimestamp(int columnIndex, java.sql.Timestamp x) throws SQLException {
4683 // sanity check.
4684 checkIndex(columnIndex);
4685 // make sure the cursor is on a valid row
4686 checkCursor();
4687
4688 Object obj = convertTemporal(x,
4689 java.sql.Types.TIMESTAMP,
4690 RowSetMD.getColumnType(columnIndex));
4691
4692 getCurrentRow().setColumnObject(columnIndex, obj);
4693 }
4694
4695 /**
4696 * Sets the designated column in either the current row or the insert
4697 * row of this <code>CachedRowSetImpl</code> object with the given
4698 * ASCII stream value.
4699 * <P>
4700 * This method updates a column value in either the current row or
4701 * the insert row of this rowset, but it does not update the
4702 * database. If the cursor is on a row in the rowset, the
4703 * method {@link #updateRow} must be called to update the database.
4704 * If the cursor is on the insert row, the method {@link #insertRow}
4705 * must be called, which will insert the new row into both this rowset
4706 * and the database. Both of these methods must be called before the
4707 * cursor moves to another row.
4708 *
4709 * @param columnIndex the first column is <code>1</code>, the second
4710 * is <code>2</code>, and so on; must be <code>1</code> or larger
4711 * and equal to or less than the number of columns in this rowset
4712 * @param x the new column value
4713 * @param length the number of one-byte ASCII characters in the stream
4714 * @throws SQLException if this method is invoked
4715 */
4716 public void updateAsciiStream(int columnIndex, java.io.InputStream x, int length) throws SQLException {
4717 // sanity Check
4718 checkIndex(columnIndex);
4719 // make sure the cursor is on a valid row
4720 checkCursor();
4721
4722
4723 if (isString(RowSetMD.getColumnType(columnIndex)) == false &&
4724 isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4725 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4726 }
4727
4728 byte buf[] = new byte[length];
4729 try {
4730 int charsRead = 0;
4731 do {
4732 charsRead += x.read(buf, charsRead, length - charsRead);
4733 } while (charsRead != length);
4734 //Changed the condition check to check for length instead of -1
4735 } catch (java.io.IOException ex) {
4736 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.asciistream").toString());
4737 }
4738 String str = new String(buf);
4739
4740 getCurrentRow().setColumnObject(columnIndex, str);
4741
4742 }
4743
4744 /**
4745 * Sets the designated column in either the current row or the insert
4746 * row of this <code>CachedRowSetImpl</code> object with the given
4747 * <code>java.io.InputStream</code> object.
4748 * <P>
4749 * This method updates a column value in either the current row or
4750 * the insert row of this rowset, but it does not update the
4751 * database. If the cursor is on a row in the rowset, the
4752 * method {@link #updateRow} must be called to update the database.
4753 * If the cursor is on the insert row, the method {@link #insertRow}
4754 * must be called, which will insert the new row into both this rowset
4755 * and the database. Both of these methods must be called before the
4756 * cursor moves to another row.
4757 *
4758 * @param columnIndex the first column is <code>1</code>, the second
4759 * is <code>2</code>, and so on; must be <code>1</code> or larger
4760 * and equal to or less than the number of columns in this rowset
4761 * @param x the new column value; must be a <code>java.io.InputStream</code>
4762 * containing <code>BINARY</code>, <code>VARBINARY</code>, or
4763 * <code>LONGVARBINARY</code> data
4764 * @param length the length of the stream in bytes
4765 * @throws SQLException if (1) the given column index is out of bounds,
4766 * (2) the cursor is not on one of this rowset's rows or its
4767 * insert row, (3) the data in the stream is not binary, or
4768 * (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4769 */
4770 public void updateBinaryStream(int columnIndex, java.io.InputStream x,int length) throws SQLException {
4771 // sanity Check
4772 checkIndex(columnIndex);
4773 // make sure the cursor is on a valid row
4774 checkCursor();
4775
4776 if (isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4777 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4778 }
4779
4780 byte buf[] = new byte[length];
4781 try {
4782 int bytesRead = 0;
4783 do {
4784 bytesRead += x.read(buf, bytesRead, length - bytesRead);
4785 } while (bytesRead != -1);
4786 } catch (java.io.IOException ex) {
4787 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.binstream").toString());
4788 }
4789
4790 getCurrentRow().setColumnObject(columnIndex, buf);
4791 }
4792
4793 /**
4794 * Sets the designated column in either the current row or the insert
4795 * row of this <code>CachedRowSetImpl</code> object with the given
4796 * <code>java.io.Reader</code> object.
4797 * <P>
4798 * This method updates a column value in either the current row or
4799 * the insert row of this rowset, but it does not update the
4800 * database. If the cursor is on a row in the rowset, the
4801 * method {@link #updateRow} must be called to update the database.
4802 * If the cursor is on the insert row, the method {@link #insertRow}
4803 * must be called, which will insert the new row into both this rowset
4804 * and the database. Both of these methods must be called before the
4805 * cursor moves to another row.
4806 *
4807 * @param columnIndex the first column is <code>1</code>, the second
4808 * is <code>2</code>, and so on; must be <code>1</code> or larger
4809 * and equal to or less than the number of columns in this rowset
4810 * @param x the new column value; must be a <code>java.io.Reader</code>
4811 * containing <code>BINARY</code>, <code>VARBINARY</code>,
4812 * <code>LONGVARBINARY</code>, <code>CHAR</code>, <code>VARCHAR</code>,
4813 * or <code>LONGVARCHAR</code> data
4814 * @param length the length of the stream in characters
4815 * @throws SQLException if (1) the given column index is out of bounds,
4816 * (2) the cursor is not on one of this rowset's rows or its
4817 * insert row, (3) the data in the stream is not a binary or
4818 * character type, or (4) this rowset is
4819 * <code>ResultSet.CONCUR_READ_ONLY</code>
4820 */
4821 public void updateCharacterStream(int columnIndex, java.io.Reader x, int length) throws SQLException {
4822 // sanity Check
4823 checkIndex(columnIndex);
4824 // make sure the cursor is on a valid row
4825 checkCursor();
4826
4827 if (isString(RowSetMD.getColumnType(columnIndex)) == false &&
4828 isBinary(RowSetMD.getColumnType(columnIndex)) == false) {
4829 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
4830 }
4831
4832 char buf[] = new char[length];
4833 try {
4834 int charsRead = 0;
4835 do {
4836 charsRead += x.read(buf, charsRead, length - charsRead);
4837 } while (charsRead != length);
4838 //Changed the condition checking to check for length instead of -1
4839 } catch (java.io.IOException ex) {
4840 throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.binstream").toString());
4841 }
4842 String str = new String(buf);
4843
4844 getCurrentRow().setColumnObject(columnIndex, str);
4845 }
4846
4847 /**
4848 * Sets the designated column in either the current row or the insert
4849 * row of this <code>CachedRowSetImpl</code> object with the given
4850 * <code>Object</code> value. The <code>scale</code> parameter indicates
4851 * the number of digits to the right of the decimal point and is ignored
4852 * if the new column value is not a type that will be mapped to an SQL
4853 * <code>DECIMAL</code> or <code>NUMERIC</code> value.
4854 * <P>
4855 * This method updates a column value in either the current row or
4856 * the insert row of this rowset, but it does not update the
4857 * database. If the cursor is on a row in the rowset, the
4858 * method {@link #updateRow} must be called to update the database.
4859 * If the cursor is on the insert row, the method {@link #insertRow}
4860 * must be called, which will insert the new row into both this rowset
4861 * and the database. Both of these methods must be called before the
4862 * cursor moves to another row.
4863 *
4864 * @param columnIndex the first column is <code>1</code>, the second
4865 * is <code>2</code>, and so on; must be <code>1</code> or larger
4866 * and equal to or less than the number of columns in this rowset
4867 * @param x the new column value
4868 * @param scale the number of digits to the right of the decimal point (for
4869 * <code>DECIMAL</code> and <code>NUMERIC</code> types only)
4870 * @throws SQLException if (1) the given column index is out of bounds,
4871 * (2) the cursor is not on one of this rowset's rows or its
4872 * insert row, or (3) this rowset is
4873 * <code>ResultSet.CONCUR_READ_ONLY</code>
4874 */
4875 public void updateObject(int columnIndex, Object x, int scale) throws SQLException {
4876 // sanity check.
4877 checkIndex(columnIndex);
4878 // make sure the cursor is on a valid row
4879 checkCursor();
4880
4881 int type = RowSetMD.getColumnType(columnIndex);
4882 if (type == Types.DECIMAL || type == Types.NUMERIC) {
4883 ((java.math.BigDecimal)x).setScale(scale);
4884 }
4885 getCurrentRow().setColumnObject(columnIndex, x);
4886 }
4887
4888 /**
4889 * Sets the designated column in either the current row or the insert
4890 * row of this <code>CachedRowSetImpl</code> object with the given
4891 * <code>Object</code> value.
4892 * <P>
4893 * This method updates a column value in either the current row or
4894 * the insert row of this rowset, but it does not update the
4895 * database. If the cursor is on a row in the rowset, the
4896 * method {@link #updateRow} must be called to update the database.
4897 * If the cursor is on the insert row, the method {@link #insertRow}
4898 * must be called, which will insert the new row into both this rowset
4899 * and the database. Both of these methods must be called before the
4900 * cursor moves to another row.
4901 *
4902 * @param columnIndex the first column is <code>1</code>, the second
4903 * is <code>2</code>, and so on; must be <code>1</code> or larger
4904 * and equal to or less than the number of columns in this rowset
4905 * @param x the new column value
4906 * @throws SQLException if (1) the given column index is out of bounds,
4907 * (2) the cursor is not on one of this rowset's rows or its
4908 * insert row, or (3) this rowset is
4909 * <code>ResultSet.CONCUR_READ_ONLY</code>
4910 */
4911 public void updateObject(int columnIndex, Object x) throws SQLException {
4912 // sanity check.
4913 checkIndex(columnIndex);
4914 // make sure the cursor is on a valid row
4915 checkCursor();
4916
4917 getCurrentRow().setColumnObject(columnIndex, x);
4918 }
4919
4920 /**
4921 * Sets the designated nullable column in the current row or the
4922 * insert row of this <code>CachedRowSetImpl</code> object with
4923 * <code>null</code> value.
4924 * <P>
4925 * This method updates a column value in the current row or the insert
4926 * row of this rowset, but it does not update the database.
4927 * If the cursor is on a row in the rowset, the
4928 * method {@link #updateRow} must be called to update the database.
4929 * If the cursor is on the insert row, the method {@link #insertRow}
4930 * must be called, which will insert the new row into both this rowset
4931 * and the database.
4932 *
4933 * @param columnName a <code>String</code> object that must match the
4934 * SQL name of a column in this rowset, ignoring case
4935 * @throws SQLException if (1) the given column name does not match the
4936 * name of a column in this rowset, (2) the cursor is not on
4937 * one of this rowset's rows or its insert row, or (3) this
4938 * rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4939 */
4940 public void updateNull(String columnName) throws SQLException {
4941 updateNull(getColIdxByName(columnName));
4942 }
4943
4944 /**
4945 * Sets the designated column in either the current row or the insert
4946 * row of this <code>CachedRowSetImpl</code> object with the given
4947 * <code>boolean</code> value.
4948 * <P>
4949 * This method updates a column value in the current row or the insert
4950 * row of this rowset, but it does not update the database.
4951 * If the cursor is on a row in the rowset, the
4952 * method {@link #updateRow} must be called to update the database.
4953 * If the cursor is on the insert row, the method {@link #insertRow}
4954 * must be called, which will insert the new row into both this rowset
4955 * and the database. Both of these methods must be called before the
4956 * cursor moves to another row.
4957 *
4958 * @param columnName a <code>String</code> object that must match the
4959 * SQL name of a column in this rowset, ignoring case
4960 * @param x the new column value
4961 * @throws SQLException if (1) the given column name does not match the
4962 * name of a column in this rowset, (2) the cursor is not on
4963 * one of this rowset's rows or its insert row, or (3) this
4964 * rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4965 */
4966 public void updateBoolean(String columnName, boolean x) throws SQLException {
4967 updateBoolean(getColIdxByName(columnName), x);
4968 }
4969
4970 /**
4971 * Sets the designated column in either the current row or the insert
4972 * row of this <code>CachedRowSetImpl</code> object with the given
4973 * <code>byte</code> value.
4974 * <P>
4975 * This method updates a column value in the current row or the insert
4976 * row of this rowset, but it does not update the database.
4977 * If the cursor is on a row in the rowset, the
4978 * method {@link #updateRow} must be called to update the database.
4979 * If the cursor is on the insert row, the method {@link #insertRow}
4980 * must be called, which will insert the new row into both this rowset
4981 * and the database. Both of these methods must be called before the
4982 * cursor moves to another row.
4983 *
4984 * @param columnName a <code>String</code> object that must match the
4985 * SQL name of a column in this rowset, ignoring case
4986 * @param x the new column value
4987 * @throws SQLException if (1) the given column name does not match the
4988 * name of a column in this rowset, (2) the cursor is not on
4989 * one of this rowset's rows or its insert row, or (3) this
4990 * rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
4991 */
4992 public void updateByte(String columnName, byte x) throws SQLException {
4993 updateByte(getColIdxByName(columnName), x);
4994 }
4995
4996 /**
4997 * Sets the designated column in either the current row or the insert
4998 * row of this <code>CachedRowSetImpl</code> object with the given
4999 * <code>short</code> value.

5134 more lines aren’t shown here.